ZQuest Classic Coverage Report


Directory: src/
File: src/zq/zq_tiles.cpp
Date: 2025-01-12 05:57:18
Exec Total Coverage
Lines: 98 7667 1.3%
Functions: 1 199 0.5%
Branches: 14 6707 0.2%

Line Branch Exec Source
1 #include <cstring>
2 #include <cmath>
3
4 #include "base/files.h"
5 #include "base/qrs.h"
6 #include "base/dmap.h"
7 #include "base/cpool.h"
8 #include "base/autocombo.h"
9 #include "base/packfile.h"
10 #include "base/gui.h"
11 #include "base/combo.h"
12 #include "base/msgstr.h"
13 #include "base/zdefs.h"
14 #include "new_subscr.h"
15 #include "subscr.h"
16 #include "zq/zq_tiles.h"
17 #include "zq/zquest.h"
18 #include "tiles.h"
19 #include "zq/zq_misc.h"
20 #include "zq/zq_class.h"
21 #include "base/zsys.h"
22 #include "base/colors.h"
23 #include "base/qst.h"
24 #include "gui/jwin.h"
25 #include <base/new_menu.h>
26 #include "base/jwinfsel.h"
27 #include "zc/zc_custom.h"
28 #include "zq/questReport.h"
29 #include "dialog/info.h"
30 #include "dialog/scaletile.h"
31 #include "dialog/rotatetile.h"
32 #include "dialog/alert.h"
33 #include "drawing.h"
34 #include "colorname.h"
35 #include "zq/render.h"
36 #include "zinfo.h"
37 #include <fmt/format.h>
38 #include <functional>
39 #include "zq/moveinfo.h"
40 using std::set;
41
42 extern zcmodule moduledata;
43
44 #ifdef _MSC_VER
45 #define stricmp _stricmp
46 #endif
47
48 #define HIDE_USED (show_only_unused_tiles&1)
49 #define HIDE_UNUSED (show_only_unused_tiles&2)
50 #define HIDE_BLANK (show_only_unused_tiles&4)
51 #define HIDE_8BIT_MARKER (show_only_unused_tiles&8)
52
53 extern void large_dialog(DIALOG *d);
54 static void massRecolorReset4Bit();
55 static void massRecolorReset8Bit();
56 static bool massRecolorSetup(int32_t cset);
57 static void massRecolorApply(int32_t tile);
58 extern int32_t last_droplist_sel;
59 extern int32_t TilePgCursorCol, CmbPgCursorCol;
60
61 int32_t ex=0;
62 int32_t nextcombo_fake_click=0;
63 int32_t invcol=0;
64 int32_t tthighlight = 1;
65 int32_t showcolortip = 1;
66 int32_t show_quartgrid = 0, hide_grid = 0;
67
68 tiledata *newundotilebuf;
69 std::vector<newcombo> undocombobuf;
70
71 BITMAP *selection_pattern;
72 byte selection_grid[18][18];
73 byte selection_anchor=0;
74
75 enum {selection_mode_normal, selection_mode_add, selection_mode_subtract, selection_mode_exclude};
76 BITMAP *selecting_pattern;
77 int32_t selecting_x1, selecting_x2, selecting_y1, selecting_y2;
78
79 extern int32_t bidcomboscripts_cnt;
80 extern script_struct bidcomboscripts[NUMSCRIPTSCOMBODATA];
81
82 BITMAP *intersection_pattern;
83
84 byte relational_template[48][4]=
85 {
86 { 0, 0, 0, 0 },
87 { 0, 1, 0, 0 },
88 { 1, 0, 0, 0 },
89 { 1, 1, 0, 0 },
90 { 0, 0, 1, 0 },
91 { 0, 1, 1, 0 },
92 { 1, 0, 1, 0 },
93 { 1, 1, 1, 0 },
94 { 0, 0, 0, 1 },
95 { 0, 1, 0, 1 },
96 { 1, 0, 0, 1 },
97 { 1, 1, 0, 1 },
98 { 0, 0, 1, 1 },
99 { 0, 1, 1, 1 },
100 { 1, 0, 1, 1 },
101 { 1, 1, 1, 1 },
102 { 0, 2, 0, 2 },
103 { 1, 2, 0, 2 },
104 { 0, 2, 1, 2 },
105 { 1, 2, 1, 2 },
106 { 3, 3, 0, 0 },
107 { 3, 3, 1, 0 },
108 { 3, 3, 0, 1 },
109 { 3, 3, 1, 1 },
110 { 3, 4, 0, 2 },
111 { 3, 4, 1, 2 },
112 { 2, 0, 2, 0 },
113 { 2, 1, 2, 0 },
114 { 2, 0, 2, 1 },
115 { 2, 1, 2, 1 },
116 { 2, 2, 2, 2 },
117 { 4, 3, 2, 0 },
118 { 4, 3, 2, 1 },
119 { 4, 4, 2, 2 },
120 { 0, 0, 3, 3 },
121 { 0, 1, 3, 3 },
122 { 1, 0, 3, 3 },
123 { 1, 1, 3, 3 },
124 { 0, 2, 3, 4 },
125 { 1, 2, 3, 4 },
126 { 3, 3, 3, 3 },
127 { 3, 4, 3, 4 },
128 { 2, 0, 4, 3 },
129 { 2, 1, 4, 3 },
130 { 2, 2, 4, 4 },
131 { 4, 3, 4, 3 },
132 { 4, 4, 4, 4 },
133 { 5, 5, 5, 5 }
134 };
135
136 byte dungeon_carving_template[96][4]=
137 {
138 { 0, 0, 0, 0 },
139 { 0, 1, 0, 0 },
140 { 1, 0, 0, 0 },
141 { 1, 1, 0, 0 },
142 { 0, 0, 1, 0 },
143 { 0, 1, 1, 0 },
144 { 1, 0, 1, 0 },
145 { 1, 1, 1, 0 },
146 { 0, 0, 0, 1 },
147 { 0, 1, 0, 1 },
148 { 1, 0, 0, 1 },
149 { 1, 1, 0, 1 },
150 { 0, 0, 1, 1 },
151 { 0, 1, 1, 1 },
152 { 1, 0, 1, 1 },
153 { 1, 1, 1, 1 },
154 { 0, 2, 0, 2 },
155 { 1, 2, 0, 2 },
156 { 0, 2, 1, 2 },
157 { 1, 2, 1, 2 },
158 { 3, 3, 0, 0 },
159 { 3, 3, 1, 0 },
160 { 3, 3, 0, 1 },
161 { 3, 3, 1, 1 },
162 { 3, 4, 0, 2 },
163 { 3, 4, 1, 2 },
164 { 2, 0, 2, 0 },
165 { 2, 1, 2, 0 },
166 { 2, 0, 2, 1 },
167 { 2, 1, 2, 1 },
168 { 2, 2, 2, 2 },
169 { 4, 3, 2, 0 },
170 { 4, 3, 2, 1 },
171 { 4, 4, 2, 2 },
172 { 0, 0, 3, 3 },
173 { 0, 1, 3, 3 },
174 { 1, 0, 3, 3 },
175 { 1, 1, 3, 3 },
176 { 0, 2, 3, 4 },
177 { 1, 2, 3, 4 },
178 { 3, 3, 3, 3 },
179 { 3, 4, 3, 4 },
180 { 2, 0, 4, 3 },
181 { 2, 1, 4, 3 },
182 { 2, 2, 4, 4 },
183 { 4, 3, 4, 3 },
184 { 4, 4, 4, 4 },
185 { 5, 5, 5, 5 },
186
187 { 5, 5, 5, 5 },
188 { 6, 6, 6, 6 },
189 { 7, 7, 7, 7 },
190 { 7, 6, 7, 6 },
191 { 8, 8, 8, 8 },
192 { 16, 6, 8, 15 },
193 { 7, 7, 8, 8 },
194 { 7, 6, 8, 15 },
195 { 9, 9, 9, 9 },
196 { 6, 6, 9, 9 },
197 { 7, 17, 14, 9 },
198 { 7, 6, 14, 9 },
199 { 8, 9, 8, 9 },
200 { 16, 6, 8, 9 },
201 { 7, 17, 8, 9 },
202 { 7, 6, 8, 9 },
203 { 10, 10, 10, 10 },
204 { 7, 10, 14, 10 },
205 { 16, 10, 8, 10 },
206 { 7, 10, 8, 10 },
207 { 11, 11, 11, 11 },
208 { 11, 11, 8, 15 },
209 { 11, 11, 14, 9 },
210 { 11, 11, 8, 9 },
211 { 14, 14, 14, 14 },
212 { 14, 14, 8, 14 },
213 { 12, 12, 12, 12 },
214 { 12, 6, 12, 15 },
215 { 12, 17, 12, 9 },
216 { 12, 6, 12, 9 },
217 { 12, 10, 12, 10 },
218 { 15, 15, 15, 15 },
219 { 15, 15, 15, 9 },
220 { 15, 14, 12, 10 },
221 { 13, 13, 13, 13 },
222 { 16, 6, 13, 13 },
223 { 7, 17, 13, 13 },
224 { 7, 6, 13, 13 },
225 { 16, 16, 16, 16 },
226 { 7, 16, 16, 16 },
227 { 11, 11, 13, 13 },
228 { 11, 14, 13, 16 },
229 { 17, 17, 17, 17 },
230 { 17, 6, 17, 17 },
231 { 12, 10, 17, 16 },
232 { 15, 11, 17, 13 },
233 { 15, 14, 17, 16 },
234 { 18, 18, 18, 18 }
235 };
236
237 struct tile_move_data
238 {
239 int32_t copies;
240 int32_t dest_first;
241 int32_t dest_last;
242 int32_t src_first;
243 int32_t src_last;
244 int32_t dest_top;
245 int32_t dest_bottom;
246 int32_t src_top;
247 int32_t src_bottom;
248 int32_t src_left, src_right;
249 int32_t src_width, src_height;
250 int32_t dest_left, dest_right;
251 int32_t dest_width, dest_height;
252 int32_t rows, cols;
253 bool rect, move;
254
255 tile_move_data()
256 {
257 copies = dest_first = dest_last = src_first = src_last = dest_top =
258 dest_bottom = src_top = src_bottom = src_left = src_right =
259 src_width = src_height = dest_left = dest_right = dest_width =
260 dest_height = rows = cols = 0;
261 rect = move = false;
262 }
263
264 tile_move_data(tile_move_data const& other)
265 {
266 copy(other);
267 }
268
269 tile_move_data& operator=(tile_move_data const& other)
270 {
271 copy(other);
272 return *this;
273 }
274
275 void copy(tile_move_data const& other)
276 {
277 copies = other.copies;
278 dest_first = other.dest_first;
279 dest_last = other.dest_last;
280 src_first = other.src_first;
281 src_last = other.src_last;
282 dest_top = other.dest_top;
283 dest_bottom = other.dest_bottom;
284 src_top = other.src_top;
285 src_bottom = other.src_bottom;
286 src_left = other.src_left;
287 src_right = other.src_right;
288 src_width = other.src_width;
289 src_height = other.src_height;
290 dest_left = other.dest_left;
291 dest_right = other.dest_right;
292 dest_width = other.dest_width;
293 dest_height = other.dest_height;
294 rows = other.rows;
295 cols = other.cols;
296 rect = other.rect;
297 move = other.move;
298 }
299
300 void flip()
301 {
302 zc_swap(src_first, dest_first);
303 zc_swap(src_last, dest_last);
304 zc_swap(src_top, dest_top);
305 zc_swap(src_bottom, dest_bottom);
306 zc_swap(src_left, dest_left);
307 zc_swap(src_right, dest_right);
308 zc_swap(src_width, dest_width);
309 zc_swap(src_height, dest_height);
310 }
311 };
312 bool do_movetile_united(tile_move_data const& tmd);
313
314 struct combo_move_data
315 {
316 int32_t tile, tile2, copy1, copycnt;
317 combo_move_data() : tile(0), tile2(0), copy1(0), copycnt(0){}
318 combo_move_data(combo_move_data const& other)
319 {
320 copy(other);
321 }
322 combo_move_data& operator=(combo_move_data const& other)
323 {
324 copy(other);
325 return *this;
326 }
327 void copy(combo_move_data const& other)
328 {
329 tile = other.tile;
330 tile2 = other.tile2;
331 copy1 = other.copy1;
332 copycnt = other.copycnt;
333 }
334
335 void flip()
336 {
337 int32_t tcnt = tile2-tile+1;
338 int32_t cpy2 = copy1+copycnt-1;
339 zc_swap(tile,copy1);
340 tile2 = cpy2;
341 copycnt = tcnt;
342 }
343 };
344
345 bool do_movecombo(combo_move_data const& cmd, ComboMoveUndo& on_undo, bool is_undoing = false);
346 static optional<ComboMoveUndo> last_combo_move_list;
347 static optional<TileMoveUndo> last_tile_move_list;
348
349 int refl_flags = 0;
350 enum
351 {
352 REFL_90CW, REFL_HFLIP,
353 REFL_90CCW, REFL_VFLIP,
354 REFL_180, REFL_DBLFLIP,
355 REFL_MAX
356 };
357 const char *reflbtn_names[] =
358 {
359 "90 CW", "HFlip",
360 "90 CCW", "VFlip",
361 "180 Rot", "Diag Flip"
362 };
363 int bgmode = 0, xmode = 0;
364 const char *bgmodebtn_names[] =
365 {
366 "BG Color 0", "BG Trans."
367 };
368 const char *xmodebtn_names[] =
369 {
370 "X", "No X"
371 };
372 enum
373 {
374 XMODE_X, XMODE_NOX,
375 XMODE_MAX
376 };
377 enum
378 {
379 BGMODE_0, BGMODE_TRANSP,
380 BGMODE_MAX
381 };
382
383 void merge_tiles(int32_t dest_tile, int32_t src_quarter1, int32_t src_quarter2, int32_t src_quarter3, int32_t src_quarter4)
384 {
385 int32_t size=tilesize(newtilebuf[dest_tile].format)>>4;
386 int32_t size2=size>>1;
387
388 if(newtilebuf[dest_tile].data==NULL)
389 {
390 reset_tile(newtilebuf, dest_tile, newtilebuf[src_quarter1>>2].format);
391 }
392
393 int32_t i=0;
394
395 if((dest_tile<<2)+i!=src_quarter1)
396 {
397 for(int32_t j=0; j<8; ++j)
398 {
399 memcpy(&(newtilebuf[dest_tile].data[((j+((i&2)<<2))*size)+((i&1)*size2)]), &(newtilebuf[src_quarter1>>2].data[((j+((src_quarter1&2)<<2))*size)+((src_quarter1&1)*size2)]), size2);
400 }
401 }
402
403 i=1;
404
405 if((dest_tile<<2)+i!=src_quarter2)
406 {
407 for(int32_t j=0; j<8; ++j)
408 {
409 memcpy(&(newtilebuf[dest_tile].data[((j+((i&2)<<2))*size)+((i&1)*size2)]), &(newtilebuf[src_quarter2>>2].data[((j+((src_quarter2&2)<<2))*size)+((src_quarter2&1)*size2)]), size2);
410 }
411 }
412
413 i=2;
414
415 if((dest_tile<<2)+i!=src_quarter3)
416 {
417 for(int32_t j=0; j<8; ++j)
418 {
419 memcpy(&(newtilebuf[dest_tile].data[((j+((i&2)<<2))*size)+((i&1)*size2)]), &(newtilebuf[src_quarter3>>2].data[((j+((src_quarter3&2)<<2))*size)+((src_quarter3&1)*size2)]), size2);
420 }
421 }
422
423 i=3;
424
425 if((dest_tile<<2)+i!=src_quarter4)
426 {
427 for(int32_t j=0; j<8; ++j)
428 {
429 memcpy(&(newtilebuf[dest_tile].data[((j+((i&2)<<2))*size)+((i&1)*size2)]), &(newtilebuf[src_quarter4>>2].data[((j+((src_quarter4&2)<<2))*size)+((src_quarter4&1)*size2)]), size2);
430 }
431 }
432 }
433
434 static void make_combos(int32_t startTile, int32_t endTile, int32_t cs)
435 {
436 al_trace("inside make_combos()\n");
437 int32_t startCombo=0;
438
439 if(!select_combo_2(startCombo,cs))
440 return;
441
442 int32_t temp=combobuf[startCombo].o_tile;
443 combobuf[startCombo].set_tile(startTile);
444
445 if(!edit_combo(startCombo, false, cs))
446 {
447 combobuf[startCombo].set_tile(temp);
448 return;
449 }
450
451 go_combos();
452
453 for(int32_t i=0; i<=endTile-startTile; i++)
454 {
455 combobuf[startCombo+i]=combobuf[startCombo];
456 combobuf[startCombo+i].set_tile(startTile+i);
457 }
458
459 setup_combo_animations();
460 setup_combo_animations2();
461 }
462
463 static void make_combos_rect(int32_t top, int32_t left, int32_t numRows, int32_t numCols, int32_t cs)
464 {
465 int32_t startCombo=0;
466
467 if(!select_combo_2(startCombo, cs))
468 return;
469
470 int32_t startTile=top*TILES_PER_ROW+left;
471 int32_t temp=combobuf[startCombo].o_tile;
472 combobuf[startCombo].set_tile(startTile);
473
474 if(!edit_combo(startCombo, false, cs))
475 {
476 al_trace("make_combos_rect() early return\n");
477 combobuf[startCombo].set_tile(temp);
478 return;
479 }
480
481 bool smartWrap=false;
482 if(numCols!=4 && numRows>1)
483 {
484 char buf[64];
485 if(numCols<4)
486 sprintf(buf, "Limit to %d column%s?", numCols, numCols==1 ? "" : "s");
487 else
488 sprintf(buf, "Fit to 4 columns?"); // Meh, whatever.
489 int32_t ret=jwin_alert("Wrapping", buf, NULL, NULL, "&Yes", "&No", 'y', 'n', get_zc_font(font_lfont));
490 if(ret==1)
491 smartWrap=true;
492 }
493
494 go_combos();
495
496 int32_t combo=startCombo-1;
497 for(int32_t row=0; row<numRows; row++)
498 {
499 for(int32_t col=0; col<numCols; col++)
500 {
501 int32_t tile=startTile+row*TILES_PER_ROW+col;
502 if(smartWrap)
503 // Add 4 per row, and another numRows*4 for every 4 columns
504 // (col&0xFC==col/4*4), and then the column %4
505 combo=startCombo+4*row+(col&0xFC)*numRows+col%4;
506 else
507 combo++;
508
509 combobuf[combo]=combobuf[startCombo];
510 combobuf[combo].set_tile(tile);
511 }
512 }
513
514 setup_combo_animations();
515 setup_combo_animations2();
516 }
517
518 int32_t d_combo_proc(int32_t msg,DIALOG *d,int32_t c);
519
520 static bool nogotiles = false;
521 static bool nogocombos = false;
522
523 void go_tiles()
524 {
525 if(nogotiles) return;
526 last_tile_move_list = nullopt;
527 for(int32_t i=0; i<NEWMAXTILES; ++i)
528 {
529 newundotilebuf[i].format=newtilebuf[i].format;
530
531 if(newundotilebuf[i].data!=NULL)
532 {
533 free(newundotilebuf[i].data);
534 }
535
536 newundotilebuf[i].data=(byte *)malloc(tilesize(newundotilebuf[i].format));
537
538 if(newundotilebuf[i].data==NULL)
539 {
540 Z_error_fatal("Unable to initialize undo tile #%ld.\n", i);
541 }
542
543 memcpy(newundotilebuf[i].data,newtilebuf[i].data,tilesize(newundotilebuf[i].format));
544 }
545 }
546
547 void go_slide_tiles(int32_t columns, int32_t rows, int32_t top, int32_t left)
548 {
549 for(int32_t c=0; c<columns; c++)
550 {
551 for(int32_t r=0; r<rows; r++)
552 {
553 int32_t t=((top+r)*TILES_PER_ROW)+left+c;
554 newundotilebuf[t].format=newtilebuf[t].format;
555
556 if(newundotilebuf[t].data!=NULL)
557 {
558 free(newundotilebuf[t].data);
559 }
560
561 newundotilebuf[t].data=(byte *)malloc(tilesize(newundotilebuf[t].format));
562
563 if(newundotilebuf[t].data==NULL)
564 {
565 Z_error_fatal("Unable to initialize undo tile #%ld.\n", t);
566 }
567
568 memcpy(newundotilebuf[t].data,newtilebuf[t].data,tilesize(newundotilebuf[t].format));
569 }
570 }
571 }
572
573 void comeback_tiles()
574 {
575 if(last_tile_move_list)
576 {
577 last_tile_move_list->undo();
578 last_tile_move_list = nullopt;
579 }
580 for(dword i=0; i<NEWMAXTILES; ++i)
581 {
582 if(newtilebuf[i].format != newundotilebuf[i].format || !newtilebuf[i].data)
583 {
584 newtilebuf[i].format = newundotilebuf[i].format;
585
586 if(newtilebuf[i].data!=NULL)
587 free(newtilebuf[i].data);
588 newtilebuf[i].data=(byte *)malloc(tilesize(newtilebuf[i].format));
589 if(newtilebuf[i].data==NULL)
590 Z_error_fatal("Unable to initialize tile #%ld.\n", i);
591 }
592
593 memcpy(newtilebuf[i].data,newundotilebuf[i].data,tilesize(newtilebuf[i].format));
594 }
595
596 register_blank_tiles();
597 register_used_tiles();
598 }
599
600 void go_combos()
601 {
602 if(nogocombos) return;
603 last_combo_move_list = nullopt;
604
605 undocombobuf = combobuf;
606 }
607
608 void comeback_combos()
609 {
610 if(last_combo_move_list)
611 {
612 last_combo_move_list->undo();
613 last_combo_move_list = nullopt;
614 }
615
616 combobuf = undocombobuf;
617 }
618
619 void little_x(BITMAP *dest, int32_t x, int32_t y, int32_t c, int32_t s)
620 {
621 line(dest,x,y,x+s,y+s,c);
622 line(dest,x+s,y,x,y+s,c);
623 }
624 void little_x(BITMAP *dest, int32_t x, int32_t y, int32_t c, int32_t w, int32_t h)
625 {
626 line(dest,x,y,x+w,y+h,c);
627 line(dest,x+w,y,x,y+h,c);
628 }
629
630 enum {gm_light, gm_dark, gm_max};
631 int32_t gridmode=gm_light;
632
633 bool has_selection()
634 {
635 for(int32_t i=1; i<17; ++i)
636 {
637 for(int32_t j=1; j<17; ++j)
638 {
639 if(selection_grid[i][j])
640 {
641 return true;
642 }
643 }
644 }
645
646 return false;
647 }
648
649 void draw_selection_outline(BITMAP *dest, int32_t x, int32_t y, int32_t scale2)
650 {
651 drawing_mode(DRAW_MODE_COPY_PATTERN, selection_pattern, selection_anchor>>3, 0);
652
653 for(int32_t i=1; i<18; ++i)
654 {
655 for(int32_t j=1; j<18; ++j)
656 {
657 // zoomtile16(screen2,tile,79,31,cs,flip,8);
658 if(selection_grid[i-1][j]!=selection_grid[i][j])
659 {
660 vline(dest, x+((i-1)*scale2), y+((j-1)*scale2), y+(j*scale2), 255);
661 }
662
663 if(selection_grid[i][j-1]!=selection_grid[i][j])
664 {
665 hline(dest, x+((i-1)*scale2), y+((j-1)*scale2), x+(i*scale2), 255);
666 }
667 }
668 }
669
670 drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0);
671 // selection_anchor=(selection_anchor+1)%64;
672 }
673
674 bool is_selecting()
675 {
676 return (selecting_x1>-1&&selecting_x2>-1&&selecting_y1>-1&&selecting_y2>-1);
677 }
678
679 void draw_selecting_outline(BITMAP *dest, int32_t x, int32_t y, int32_t scale2)
680 {
681 int32_t x1=zc_min(selecting_x1,selecting_x2);
682 int32_t x2=zc_max(selecting_x1,selecting_x2);
683 int32_t y1=zc_min(selecting_y1,selecting_y2);
684 int32_t y2=zc_max(selecting_y1,selecting_y2);
685
686 // rect(dest, x+(x1*scale2), y+(y1*scale2), x+((x2+1)*scale2), y+((y2+1)*scale2), 255);
687 for(int32_t i=1; i<18; ++i)
688 {
689 for(int32_t j=1; j<18; ++j)
690 {
691 drawing_mode(DRAW_MODE_COPY_PATTERN, selecting_pattern, selection_anchor>>3, 0);
692
693 if(((j>=y1+1)&&(j<=y2+1))&&((i==x1+1)||(i==x2+2)))
694 {
695 if(selection_grid[i-1][j]!=selection_grid[i][j])
696 {
697 drawing_mode(DRAW_MODE_COPY_PATTERN, intersection_pattern, selection_anchor>>3, 0);
698 }
699
700 vline(dest, x+((i-1)*scale2), y+((j-1)*scale2), y+(j*scale2), 255);
701 }
702
703 if(((i>=x1+1)&&(i<=x2+1))&&((j==y1+1)||(j==y2+2)))
704 {
705 if(selection_grid[i][j-1]!=selection_grid[i][j])
706 {
707 drawing_mode(DRAW_MODE_COPY_PATTERN, intersection_pattern, selection_anchor>>3, 0);
708 }
709
710 hline(dest, x+((i-1)*scale2), y+((j-1)*scale2), x+(i*scale2), 255);
711 }
712 }
713 }
714
715 drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0);
716 // selection_anchor=(selection_anchor+1)%64;
717 }
718
719 void unfloat_selection();
720 bool floating_sel = false;
721 byte floatsel[256];
722 byte undofloatsel[256];
723 bool undo_is_floatsel = false;
724
725
726 void add_color_to_selection(int32_t color)
727 {
728 unfloat_selection();
729 for(int32_t i=1; i<17; ++i)
730 {
731 for(int32_t j=1; j<17; ++j)
732 {
733 if(unpackbuf[((j-1)<<4)+(i-1)]==color)
734 {
735 selection_grid[i][j]=1;
736 }
737 }
738 }
739 }
740
741 void remove_color_from_selection(int32_t color)
742 {
743 unfloat_selection();
744 for(int32_t i=1; i<17; ++i)
745 {
746 for(int32_t j=1; j<17; ++j)
747 {
748 if(unpackbuf[((j-1)<<4)+(i-1)]==color)
749 {
750 selection_grid[i][j]=0;
751 }
752 }
753 }
754 }
755
756 void intersect_color_with_selection(int32_t color)
757 {
758 unfloat_selection();
759 for(int32_t i=1; i<17; ++i)
760 {
761 for(int32_t j=1; j<17; ++j)
762 {
763 if((unpackbuf[((j-1)<<4)+(i-1)]==color)&&(selection_grid[i][j]==1))
764 {
765 selection_grid[i][j]=1;
766 }
767 else
768 {
769 selection_grid[i][j]=0;
770 }
771 }
772 }
773 }
774
775 bool is_in_selection(int32_t x, int32_t y)
776 {
777 x %= 16; y %= 16;
778 if(x < 0) x = (16 - abs(x));
779 if(y < 0) y = (16 - abs(y));
780 return (!has_selection()||(selection_grid[x+1][y+1]!=0));
781 }
782
783 void zoomtile16(BITMAP *dest,int32_t tile,int32_t x,int32_t y,int32_t cset,int32_t flip,int32_t m)
784 {
785 // rectfill(dest,x,y,x+(16*m),y+(16*m),gridmode==gm_light?jwin_pal[jcMEDLT]:jwin_pal[jcDARK]);
786 int gridcol = gridmode==gm_light?vc(7):vc(8);
787
788 cset <<= 4;
789 if(newtilebuf[tile].format>tf4Bit)
790 cset=0;
791
792 int g = hide_grid ? 1 : 0;
793 byte transp_col = (bgmode == BGMODE_TRANSP ? jwin_pal[jcBOX] : 0+cset);
794 rectfill(dest,x,y,x+(16*m)+g,y+(16*m)+g,transp_col);
795
796 unpack_tile(newtilebuf, tile, 0, false);
797 byte *si = unpackbuf;
798 for(int32_t cy=0; cy<16; cy++)
799 {
800 for(int32_t cx=0; cx<16; cx++)
801 {
802 byte col = (floating_sel && floatsel[cx+(cy<<4)]) ? floatsel[cx+(cy<<4)] : *si;
803 int32_t dx = ((flip&1)?15-cx:cx)*m;
804 int32_t dy = ((flip&2)?15-cy:cy)*m;
805 if(col)
806 rectfill(dest,x+dx,y+dy,x+dx+m-1,y+dy+m-1,col+cset);
807
808 if(!col && xmode == XMODE_X)
809 little_x(dest,x+dx+m/4,y+dy+m/4,invcol,m/2);
810
811 ++si;
812 }
813 }
814
815 if(!hide_grid)
816 {
817 for(int cx = 0; cx <= 16; ++cx)
818 vline(dest,x+(cx*m),y,y+(16*m)-1,gridcol);
819 for(int cy = 0; cy <= 16; ++cy)
820 hline(dest,x,y+(cy*m),x+(16*m)-1,gridcol);
821 }
822
823 if(show_quartgrid)
824 {
825 int offs = (8*m);
826 const int RAD = 3;
827 rectfill(dest,x+offs-RAD,y,x+offs+RAD,y+(16*m),gridcol);
828 rectfill(dest,x,y+offs-RAD,x+(16*m),y+offs+RAD,gridcol);
829 }
830
831 if(has_selection()||is_selecting())
832 {
833 selection_anchor=(selection_anchor+1)%64;
834
835 if(has_selection()||is_selecting())
836 draw_selection_outline(dest, x, y, m);
837
838 if(is_selecting())
839 draw_selecting_outline(dest, x, y, m);
840 }
841 }
842
843 void draw_text_button(BITMAP *dest,int32_t x,int32_t y,int32_t w,int32_t h,const char *text,int32_t bg,int32_t fg,int32_t flags,bool jwin)
844 {
845 if(!jwin)
846 {
847 if(flags&D_SELECTED)
848 {
849 zc_swap(fg,bg);
850 }
851
852 rect(dest,x+1,y+1,x+w-1,y+h-1,fg);
853 rectfill(dest,x+1,y+1,x+w-3,y+h-3,bg);
854 rect(dest,x,y,x+w-2,y+h-2,fg);
855 textout_centre_ex(dest,font,text,(x+x+w)>>1,((y+y+h)>>1)-4,fg,-1);
856 }
857 else
858 {
859 jwin_draw_text_button(dest, x, y, w, h, text, flags, true);
860 }
861 }
862
863 void draw_icon_button(BITMAP *dest,int32_t x,int32_t y,int32_t w,int32_t h,int icon,int32_t bg,int32_t fg,int32_t flags,bool jwin)
864 {
865 if(!jwin)
866 {
867 if(flags&D_SELECTED)
868 {
869 zc_swap(fg,bg);
870 }
871
872 rect(dest,x+1,y+1,x+w-1,y+h-1,fg);
873 rectfill(dest,x+1,y+1,x+w-3,y+h-3,bg);
874 rect(dest,x,y,x+w-2,y+h-2,fg);
875 jwin_draw_icon(dest,x+w/2,y+h/2,fg,icon,icon_proportion(icon,w,h),true);
876 }
877 else
878 {
879 jwin_draw_icon_button(dest, x, y, w, h, icon, flags, true);
880 }
881 }
882
883 void draw_layer_button(BITMAP *dest,int32_t x,int32_t y,int32_t w,int32_t h,const char *text,int32_t flags)
884 {
885 if(flags&D_SELECTED)
886 {
887 rect(dest, x, y, x+w-1, y+h-1, jwin_pal[jcDARK]);
888 ++x;
889 ++y;
890 --w;
891 --h;
892 }
893 rectfill(dest,x+1,y+1,x+w-3,y+h-3,jwin_pal[(flags&D_SELECTED ? jcMEDDARK : jcBOX)]);
894 jwin_draw_frame(dest, x, y, w, h, (flags&D_SELECTED ? FR_DARK : FR_BOX));
895
896 //Forcibly fit the text within the button
897 char buf[512] = {0};
898 strcpy(buf, text);
899
900 bool dis = (flags&D_DISABLED);
901 auto hei = text_height(font);
902 auto len = text_length(font,buf);
903 auto borderwid = 8;
904 if(len > w - borderwid + (dis ? 1 : 0))
905 {
906 auto ind = strlen(buf) - 1;
907 auto dotcount = 0;
908 while(len > w - borderwid + (dis ? 1 : 0))
909 {
910 if(dotcount >= 2)
911 buf[ind+2] = 0;
912 else ++dotcount;
913 buf[ind--] = '.';
914 len = text_length(font,buf);
915 }
916 }
917 if(dis)
918 {
919 ++len; ++hei;
920 }
921 BITMAP* tmp = create_bitmap_ex(8,len,hei);
922 clear_bitmap(tmp);
923 if(dis)
924 {
925 textout_ex(tmp,font,buf,1,1,jwin_pal[jcLIGHT],-1);
926 textout_ex(tmp,font,buf,0,0,jwin_pal[jcDISABLED_FG],-1);
927 }
928 else
929 textout_ex(tmp,font,buf,0,0,jwin_pal[jcBOXFG],-1);
930 auto tx = x+((w-len)/2);
931 auto ty = y+((h-hei)/2);
932 if(len > w-borderwid)
933 {
934 tx = x+borderwid/2;
935 len = w-borderwid;
936 }
937 if(hei > h-borderwid)
938 {
939 ty = y+borderwid/2;
940 hei = h-borderwid;
941 }
942 masked_blit(tmp,dest, 0,0, tx,ty, len, hei);
943 destroy_bitmap(tmp);
944 }
945
946 bool do_layer_button_reset(int32_t x,int32_t y,int32_t w,int32_t h,const char *text, int32_t flags, bool toggleflag)
947 {
948 bool over=false;
949
950 while(gui_mouse_b())
951 {
952 //vsync();
953 if(mouse_in_rect(x,y,w,h))
954 {
955 if(!over)
956 {
957 vsync();
958 draw_layer_button(screen, x, y, w, h, text, flags^D_SELECTED);
959 over=true;
960
961 update_hw_screen();
962 }
963 }
964 else
965 {
966 if(over)
967 {
968 vsync();
969 draw_layer_button(screen, x, y, w, h, text, flags);
970 over=false;
971
972 update_hw_screen();
973 }
974 }
975 rest(1);
976 }
977
978 if(over)
979 {
980 vsync();
981 draw_layer_button(screen, x, y, w, h, text, toggleflag ? flags^D_SELECTED : flags);
982
983 update_hw_screen();
984 }
985
986 return over;
987 }
988
989 bool do_text_button_reset(int32_t x,int32_t y,int32_t w,int32_t h,const char *text,int32_t bg,int32_t fg,bool jwin, bool sel)
990 {
991 bool over=false;
992
993 while(gui_mouse_b())
994 {
995 custom_vsync();
996
997 if(isinRect(gui_mouse_x(),gui_mouse_y(),x,y,x+w-1,y+h-1))
998 {
999 if(!over)
1000 {
1001 draw_text_button(screen,x,y,w,h,text,fg,bg,sel?0:D_SELECTED,jwin);
1002 over=true;
1003 }
1004 }
1005 else
1006 {
1007 if(over)
1008 {
1009 draw_text_button(screen,x,y,w,h,text,fg,bg,sel?D_SELECTED:0,jwin);
1010 over=false;
1011 }
1012 }
1013 }
1014
1015 if(over)
1016 {
1017 custom_vsync();
1018 draw_text_button(screen,x,y,w,h,text,fg,bg,sel?0:D_SELECTED,jwin);
1019 }
1020
1021 return over;
1022 }
1023
1024 void draw_graphics_button(BITMAP *dest,int32_t x,int32_t y,int32_t w,int32_t h,BITMAP *bmp,BITMAP *bmp2,int32_t bg,int32_t fg,int32_t flags,bool jwin,bool overlay)
1025 {
1026 if(!jwin)
1027 {
1028 if(flags&D_SELECTED)
1029 {
1030 zc_swap(fg,bg);
1031 }
1032
1033 rect(dest,x+1,y+1,x+w-1,y+h-1,fg);
1034 rectfill(dest,x+1,y+1,x+w-3,y+h-3,bg);
1035 rect(dest,x,y,x+w-2,y+h-2,fg);
1036 int32_t g = (flags & D_SELECTED) ? 1 : 0;
1037
1038 if(overlay)
1039 {
1040 masked_blit(bmp, dest, 0, 0, x+w/2+g, y+h/2-bmp->h/2+g, bmp->h, bmp->w);
1041 }
1042 else
1043 {
1044 blit(bmp, dest, 0, 0, x+w/2+g, y+h/2-bmp->h/2+g, bmp->h, bmp->w);
1045 }
1046 }
1047 else
1048 {
1049 jwin_draw_graphics_button(dest, x, y, w, h, bmp, bmp2, flags, false, overlay);
1050 }
1051 }
1052
1053 bool do_graphics_button(int32_t x,int32_t y,int32_t w,int32_t h,BITMAP *bmp,BITMAP *bmp2,int32_t bg,int32_t fg,bool jwin,bool overlay)
1054 {
1055 bool over=false;
1056
1057 while(gui_mouse_b())
1058 {
1059 custom_vsync();
1060
1061 if(isinRect(gui_mouse_x(),gui_mouse_y(),x,y,x+w-1,y+h-1))
1062 {
1063 if(!over)
1064 {
1065 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,D_SELECTED,jwin,overlay);
1066 over=true;
1067 }
1068 }
1069 else
1070 {
1071 if(over)
1072 {
1073 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,0,jwin,overlay);
1074 over=false;
1075 }
1076 }
1077 }
1078
1079 return over;
1080 }
1081
1082 bool do_graphics_button_reset(int32_t x,int32_t y,int32_t w,int32_t h,BITMAP *bmp,BITMAP *bmp2,int32_t bg,int32_t fg,bool jwin,bool overlay)
1083 {
1084 bool over=false;
1085
1086 while(gui_mouse_b())
1087 {
1088 custom_vsync();
1089
1090 if(isinRect(gui_mouse_x(),gui_mouse_y(),x,y,x+w-1,y+h-1))
1091 {
1092 if(!over)
1093 {
1094 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,D_SELECTED,jwin,overlay);
1095 over=true;
1096 }
1097 }
1098 else
1099 {
1100 if(over)
1101 {
1102 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,0,jwin,overlay);
1103 over=false;
1104 }
1105 }
1106 }
1107
1108 if(over)
1109 {
1110 custom_vsync();
1111 draw_graphics_button(screen,x,y,w,h,bmp,bmp2,fg,bg,0,jwin,overlay);
1112 }
1113
1114 return over;
1115 }
1116 // circle(BITMAP *bmp, int32_t x, int32_t y, int32_t radius, int32_t color);
1117 // circlefill(BITMAP *bmp, int32_t x, int32_t y, int32_t radius, int32_t color);
1118
1119 void draw_layerradio(BITMAP *dest,int32_t x,int32_t y,int32_t bg,int32_t fg, int32_t value)
1120 {
1121 //these are here to bypass compiler warnings about unused arguments
1122 bg=bg;
1123 fg=fg;
1124
1125 int32_t r, center;
1126
1127 for(int32_t k=0; k<7; k++)
1128 {
1129 if((k==0)||(Map.CurrScr()->layermap[k-1]))
1130 {
1131 // circle(dest, x+(k*25)+4, y+4, 4, fg);
1132 // circlefill(dest, x+(k*25)+4, y+4, 2, (value==k)?fg:bg);
1133 //*
1134 r = 9/2;
1135
1136 center = x+(k*25)+r;
1137 rectfill(dest, x+(k*25), y, x+(k*25)+9-1, y+9-1, jwin_pal[jcBOX]);
1138
1139 circlefill(dest, center, y+r, r, jwin_pal[jcLIGHT]);
1140 arc(dest, center, y+r, itofix(32), itofix(160), r, jwin_pal[jcMEDDARK]);
1141 circlefill(dest, center, y+r, r-1, jwin_pal[jcMEDLT]);
1142 arc(dest, center, y+r, itofix(32), itofix(160), r-1, jwin_pal[jcDARK]);
1143 circlefill(dest, center, y+r, r-2, jwin_pal[jcLIGHT]);
1144
1145 if(value==k)
1146 {
1147 circlefill(dest, center, y+r, r-3, jwin_pal[jcDARK]);
1148 }
1149
1150 //*/
1151 }
1152 }
1153 }
1154
1155 void do_layerradio(BITMAP *dest,int32_t x,int32_t y,int32_t bg,int32_t fg,int32_t &value)
1156 {
1157 while(gui_mouse_b())
1158 {
1159 custom_vsync();
1160
1161 for(int32_t k=0; k<7; k++)
1162 {
1163 if((k==0)||(Map.CurrScr()->layermap[k-1]))
1164 {
1165 //if on radio button
1166 if(isinRect(gui_mouse_x(),gui_mouse_y(),x+(k*25),y,x+(k*25)+8,y+8))
1167 {
1168 value=k;
1169 draw_layerradio(dest,x,y,bg,fg,value);
1170 refresh(rMENU);
1171 }
1172 }
1173 }
1174 }
1175 }
1176
1177 //*************** tile flood fill stuff **************
1178
1179 byte tf_c;
1180 byte tf_u;
1181
1182 void tile_floodfill_rec(int32_t x,int32_t y)
1183 {
1184 if(is_in_selection(x,y))
1185 {
1186 while(x>0 && (unpackbuf[(y<<4)+x-1] == tf_u))
1187 --x;
1188
1189 while(x<=15 && (unpackbuf[(y<<4)+x] == tf_u))
1190 {
1191 if(is_in_selection(x,y))
1192 {
1193 unpackbuf[(y<<4)+x] = tf_c;
1194 }
1195
1196 if(y>0 && (unpackbuf[((y-1)<<4)+x] == tf_u))
1197 tile_floodfill_rec(x,y-1);
1198
1199 if(y<15 && (unpackbuf[((y+1)<<4)+x] == tf_u))
1200 tile_floodfill_rec(x,y+1);
1201
1202 ++x;
1203 }
1204 }
1205 }
1206
1207 void tile_floodfill(int32_t tile,int32_t x,int32_t y,byte c)
1208 {
1209 if(is_in_selection(x,y))
1210 {
1211 if(floating_sel)
1212 {
1213 memcpy(unpackbuf, floatsel, 256);
1214 }
1215 else unpack_tile(newtilebuf, tile, 0, false);
1216 tf_c = c;
1217 tf_u = unpackbuf[(y<<4)+x];
1218
1219 if(tf_u != tf_c)
1220 tile_floodfill_rec(x,y);
1221 if(floating_sel)
1222 {
1223 memcpy(floatsel, unpackbuf, 256);
1224 }
1225 else pack_tile(newtilebuf,unpackbuf,tile);
1226 }
1227 }
1228
1229 //***************** tile editor stuff *****************
1230 9 size_and_pos ok_button(302,562,71,21);
1231 9 size_and_pos cancel_button(376,562,71,21);
1232 9 size_and_pos edit_button(550,562,86,21);
1233 9 size_and_pos hlcbox(742,392,16,16);
1234 9 size_and_pos hov_prev(742,338,50,50);
1235 9 size_and_pos cpalette_4(648,416,4,4,64,64);
1236 9 size_and_pos cpalette_8(648,416,16,14,16,18);
1237 9 size_and_pos fg_prev(648,316,50,50);
1238 9 size_and_pos bg_prev(648+30,316+30,50,50);
1239 9 size_and_pos zoomtile(124,32,16,16,32,32);
1240 9 size_and_pos prev_til_1(648,31,96,96);
1241 9 size_and_pos prev_til_2(752,31,96,96);
1242 9 size_and_pos prev_til_3(648,135,96,96);
1243 9 size_and_pos prev_til_4(752,135,96,96);
1244 9 size_and_pos status_info(648,308-(4*8),1,4,1,8);
1245 9 size_and_pos hover_info(742,338-(3*8),1,3,1,8);
1246 9 size_and_pos color_info(4,189,1,1,116,8);
1247 9 size_and_pos color_info_btn(24,189,96,21);
1248 9 size_and_pos tool_btns(22,29,2,4,39,39);
1249 9 size_and_pos x_btn(890,5,15,13);
1250 9 size_and_pos info_btn(872,5,15,13);
1251 9 size_and_pos hidegrid_cbox(124,552,16,16);
1252 9 size_and_pos quartgrid_cbox(124,572,16,16);
1253 9 size_and_pos reflbtn_grid(124,610,2,3,71,21);
1254 9 size_and_pos xmodebtn_grid(300,610,1,2,90,21);
1255 9 size_and_pos bgmodebtn_grid(390,610,1,2,90,21);
1256
1257 int32_t c1=1;
1258 int32_t c2=0;
1259 int32_t floating_tile = -1;
1260 int32_t tool = t_pen;
1261 int32_t old_tool = -1;
1262 int32_t tool_cur = -1;
1263 int32_t select_mode = 0;
1264 int32_t drawing=0;
1265
1266 bool qgrid_tool(int tool)
1267 {
1268 switch(tool)
1269 {
1270 case t_pen:
1271 case t_fill:
1272 case t_recolor:
1273 case t_wand:
1274 return true;
1275 }
1276 return false;
1277 }
1278
1279 void set_tool_sprite(int tool, int type)
1280 {
1281 int spr = ZQM_NORMAL;
1282 switch(tool)
1283 {
1284 case t_pen: spr = ZQM_SWORD; break;
1285 case t_fill: spr = ZQM_POTION; break;
1286 case t_recolor: spr = ZQM_WAND; break;
1287 case t_eyedropper: spr = ZQM_LENS; break;
1288 case t_move: spr = ZQM_GLOVE_OPEN+type; break;
1289 case t_select: spr = ZQM_HOOK_PLAIN+type; break;
1290 case t_wand: spr = ZQM_SEL_WAND_PLAIN+type; break;
1291 }
1292 MouseSprite::set(spr);
1293 }
1294 void update_tool_cursor()
1295 {
1296 int32_t temp_mouse_x=gui_mouse_x();
1297 int32_t temp_mouse_y=gui_mouse_y();
1298
1299 int32_t type=0;
1300
1301 if(has_selection())
1302 {
1303 switch(tool)
1304 {
1305 case t_select:
1306 case t_wand:
1307 type+=select_mode;
1308 break;
1309 }
1310 }
1311
1312 if(isinRect(temp_mouse_x,temp_mouse_y,zoomtile.x,zoomtile.y-(tool==t_fill ? (14) : 0),zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
1313 {
1314 if(tool_cur==-1)
1315 set_tool_sprite(tool,type);
1316
1317 tool_cur=tool;
1318 }
1319 else if(tool_cur != -1)
1320 {
1321 MouseSprite::set(ZQM_NORMAL);
1322 tool_cur = -1;
1323 }
1324 }
1325
1326 void draw_edit_scr(int32_t tile,int32_t flip,int32_t cs,byte *oldtile, bool create_tbar)
1327 {
1328 PALETTE tpal;
1329 static BITMAP *tbar = create_bitmap_ex(8,zq_screen_w-6, 18);
1330 static BITMAP *preview_bmp = create_bitmap_ex(8, 64, 64);
1331 jwin_draw_win(screen2, 0, 0, zq_screen_w, zq_screen_h, FR_WIN);
1332
1333 if(!create_tbar)
1334 {
1335 blit(tbar, screen2, 0, 0, 3, 3, zq_screen_w-6, 18);
1336 }
1337 else
1338 {
1339 jwin_draw_titlebar(tbar, 0, 0, zq_screen_w-6, 18, "", true, true);
1340 blit(tbar, screen2, 0, 0, 3, 3, zq_screen_w-6, 18);
1341 }
1342
1343 textprintf_ex(screen2,get_zc_font(font_lfont),5,5,jwin_pal[jcTITLEFG],-1,"Tile Editor (%d)",tile);
1344
1345 clear_to_color(preview_bmp, 0);
1346
1347 zc_swap(oldtile,newtilebuf[tile].data); //Put oldtile in the tile buffer
1348 jwin_draw_win(screen2, prev_til_1.x-2,prev_til_1.y-2, prev_til_1.w+4, prev_til_1.h+4, FR_DEEP);
1349 puttile16(preview_bmp,tile,0,0,cs,flip);
1350 stretch_blit(preview_bmp, screen2, 0, 0, 16, 16, prev_til_1.x, prev_til_1.y, prev_til_1.w, prev_til_1.h);
1351
1352 clear_to_color(preview_bmp, 0);
1353 jwin_draw_win(screen2, prev_til_2.x-2,prev_til_2.y-2, prev_til_2.w+4, prev_til_2.h+4, FR_DEEP);
1354 overtile16(preview_bmp,tile,0,0,cs,flip);
1355 masked_stretch_blit(preview_bmp, screen2, 0, 0, 16, 16, prev_til_2.x, prev_til_2.y, prev_til_2.w, prev_til_2.h);
1356 zc_swap(oldtile,newtilebuf[tile].data); //Swap the real tile back to the buffer
1357
1358 unpack_tile(newtilebuf, tile, 0, true);
1359 if(floating_sel)
1360 for(auto q = 0; q < 256; ++q)
1361 if(floatsel[q])
1362 unpackbuf[q] = floatsel[q];
1363 byte tmptile[256];
1364 byte *tmpptr = tmptile;
1365 zc_swap(tmpptr,newtilebuf[tile].data); //Put temp data in the tile buffer
1366 pack_tile(newtilebuf,unpackbuf,tile);
1367 clear_to_color(preview_bmp, 0);
1368
1369 jwin_draw_win(screen2, prev_til_3.x-2,prev_til_3.y-2, prev_til_3.w+4, prev_til_3.h+4, FR_DEEP);
1370 puttile16(preview_bmp,tile,0,0,cs,flip);
1371 stretch_blit(preview_bmp, screen2, 0, 0, 16, 16, prev_til_3.x, prev_til_3.y, prev_til_3.w, prev_til_3.h);
1372
1373 clear_to_color(preview_bmp, 0);
1374 jwin_draw_win(screen2, prev_til_4.x-2,prev_til_4.y-2, prev_til_4.w+4, prev_til_4.h+4, FR_DEEP);
1375 overtile16(preview_bmp,tile,0,0,cs,flip);
1376 masked_stretch_blit(preview_bmp, screen2, 0, 0, 16, 16, prev_til_4.x, prev_til_4.y, prev_til_4.w, prev_til_4.h);
1377
1378 //Color info
1379 {
1380 auto fh = color_info.yscale = text_height(font);
1381 int y = color_info.y;
1382 int rx = color_info.x+color_info.xscale;
1383 color_info.h = 1;
1384 if(showcolortip)
1385 {
1386 gui_textout_ln(screen2,font,(unsigned char*)"Colors:",
1387 rx,y,jwin_pal[jcBOXFG],jwin_pal[jcBOX],2);
1388 auto str = get_tile_colornames(tile,cs);
1389 size_t pos = 0;
1390 char buf[512] = {0};
1391 char cbuf[16] = {0};
1392 while(pos < str.size())
1393 {
1394 y += fh;
1395 if(y+fh > zq_screen_h)
1396 break; //Out of space!
1397 auto endpos = str.find_first_of('\n',pos);
1398
1399 if(endpos == std::string::npos)
1400 {
1401 strcpy(buf,str.substr(pos).c_str());
1402 pos = str.size();
1403 }
1404 else
1405 {
1406 strcpy(buf,str.substr(pos,endpos-pos+1).c_str());
1407 pos = endpos+1;
1408 }
1409 //Ensure the name fits horizontally
1410 if(text_length(font,buf) > color_info.xscale)
1411 {
1412 size_t pos = 0;
1413 for(; buf[pos]; ++pos)
1414 {
1415 if(buf[pos] == ':')
1416 {
1417 strcpy(cbuf, buf+pos);
1418 buf[pos] = 0;
1419 break;
1420 }
1421 }
1422 size_t clen = text_length(font,cbuf);
1423 size_t dotlen = text_length(font,"..");
1424
1425 while(pos > 0 && (dotlen+clen+text_length(font,buf) > color_info.xscale))
1426 buf[--pos] = 0;
1427 while(buf[pos] == ' ')
1428 buf[pos] = 0;
1429 strcat(buf,"..");
1430 strcat(buf,cbuf);
1431 }
1432 gui_textout_ln(screen2,font,(unsigned char const*)buf,
1433 rx,y,jwin_pal[jcBOXFG],jwin_pal[jcBOX],2);
1434 ++color_info.h;
1435 }
1436 jwin_draw_frame(screen2,color_info.x-2,color_info.y-2,(color_info.w*color_info.xscale)+4,(color_info.h*color_info.yscale)+4,FR_DEEP);
1437 }
1438 else
1439 {
1440 draw_text_button(screen2,color_info_btn.x,color_info_btn.y,color_info_btn.w,color_info_btn.h,
1441 "Show Colors",vc(1),vc(14),0,true);
1442 }
1443 }
1444
1445 zc_swap(tmpptr,newtilebuf[tile].data); //Swap the real tile back to the buffer
1446
1447 jwin_draw_win(screen2, zoomtile.x-3, zoomtile.y-3, (zoomtile.w*zoomtile.xscale)+5, (zoomtile.h*zoomtile.yscale)+5, FR_DEEP);
1448 zoomtile16(screen2,tile,zoomtile.x-1,zoomtile.y-1,cs,flip,zoomtile.xscale);
1449
1450 if(floating_sel)
1451 textprintf_ex(screen2,font,status_info.x,status_info.y+0,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Floating selection");
1452 textprintf_ex(screen2,font,status_info.x,status_info.y+(1*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"tile: %d",tile);
1453 if(newtilebuf[tile].format==tf8Bit)
1454 textprintf_ex(screen2,font,status_info.x,status_info.y+(2*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"8-bit");
1455 else
1456 textprintf_ex(screen2,font,status_info.x,status_info.y+(2*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"cset: %d",cs);
1457
1458 PALETTE temppal;
1459
1460 //palette and mouse
1461 switch(newtilebuf[tile].format)
1462 {
1463 case tf4Bit:
1464 jwin_draw_win(screen2, cpalette_4.x-2, cpalette_4.y-2, (cpalette_4.xscale*cpalette_4.w)+4, (cpalette_4.yscale*cpalette_4.h)+4, FR_DEEP);
1465 get_palette(temppal);
1466
1467 for(int32_t i=0; i<cpalette_4.w*cpalette_4.h; i++)
1468 {
1469 size_and_pos const& s = cpalette_4.subsquare(i);
1470 rectfill(screen2,s.x,s.y,s.x+s.w-1,s.y+s.h-1,CSET(cs)+i);
1471 }
1472
1473 little_x(screen2,cpalette_4.x+1,cpalette_4.y+1,invcol,cpalette_4.xscale-5,cpalette_4.yscale-5);
1474 break;
1475
1476 case tf8Bit:
1477 jwin_draw_win(screen2, cpalette_8.x-2, cpalette_8.y-2, (cpalette_8.xscale*cpalette_8.w)+4, (cpalette_8.yscale*cpalette_8.h)+4, FR_DEEP);
1478
1479 for(int32_t i=0; i<cpalette_8.w*cpalette_8.h; ++i)
1480 {
1481 size_and_pos const& s = cpalette_8.subsquare(i);
1482 rectfill(screen2,s.x,s.y,s.x+s.w-1,s.y+s.h-1,i);
1483 }
1484
1485 little_x(screen2,cpalette_8.x+1,cpalette_8.y+1,invcol,cpalette_8.xscale-5,cpalette_8.yscale-5);
1486 break;
1487 }
1488
1489 rect(screen2, bg_prev.x, bg_prev.y, bg_prev.x+bg_prev.w-1, bg_prev.y+bg_prev.h-1, jwin_pal[jcTEXTFG]);
1490 rectfill(screen2, bg_prev.x+1, bg_prev.y+1, bg_prev.x+bg_prev.w-2, bg_prev.y+bg_prev.h-2, jwin_pal[jcTEXTBG]);
1491 rectfill(screen2, bg_prev.x+3, bg_prev.y+3, bg_prev.x+bg_prev.w-4, bg_prev.y+bg_prev.h-4, c2+((newtilebuf[tile].format==tf4Bit)?CSET(cs):0));
1492
1493 if(c2==0)
1494 {
1495 little_x(screen2, bg_prev.x+1, bg_prev.y+1, invcol, bg_prev.w-2, bg_prev.h-2);
1496 }
1497
1498 rect(screen2, fg_prev.x, fg_prev.y, fg_prev.x+fg_prev.w-1, fg_prev.y+fg_prev.h-1, jwin_pal[jcTEXTFG]);
1499 rectfill(screen2, fg_prev.x+1, fg_prev.y+1, fg_prev.x+fg_prev.w-2, fg_prev.y+fg_prev.h-2, jwin_pal[jcTEXTBG]);
1500 rectfill(screen2, fg_prev.x+3, fg_prev.y+3, fg_prev.x+fg_prev.w-4, fg_prev.y+fg_prev.h-4, c1+((newtilebuf[tile].format==tf4Bit)?CSET(cs):0));
1501
1502 if(c1==0)
1503 {
1504 little_x(screen2, fg_prev.x+1, fg_prev.y+1, invcol, fg_prev.w-2, fg_prev.h-2);
1505 }
1506
1507 draw_text_button(screen2,ok_button.x,ok_button.y,ok_button.w,ok_button.h,"OK",vc(1),vc(14),0,true);
1508 draw_text_button(screen2,cancel_button.x,cancel_button.y,cancel_button.w,cancel_button.h,"Cancel",vc(1),vc(14),0,true);
1509 draw_text_button(screen2,edit_button.x,edit_button.y,edit_button.w,edit_button.h,"Edit Pal",vc(1),vc(14),0,true);
1510 draw_checkbox(screen2,hlcbox.x, hlcbox.y, hlcbox.w, hlcbox.h, tthighlight);
1511 gui_textout_ln(screen2,font,(unsigned char*)"Highlight Hover",hlcbox.x+hlcbox.w+2,hlcbox.y+hlcbox.h/2-text_height(font)/2,jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1512
1513 draw_checkbox(screen2,quartgrid_cbox.x, quartgrid_cbox.y, quartgrid_cbox.w, quartgrid_cbox.h, show_quartgrid);
1514 gui_textout_ln(screen2,font,(unsigned char*)"Quarter Grid",quartgrid_cbox.x+quartgrid_cbox.w+2,quartgrid_cbox.y+quartgrid_cbox.h/2-text_height(font)/2,jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1515
1516 draw_checkbox(screen2,hidegrid_cbox.x, hidegrid_cbox.y, hidegrid_cbox.w, hidegrid_cbox.h, hide_grid);
1517 gui_textout_ln(screen2,font,(unsigned char*)"Hide Grid",hidegrid_cbox.x+hidegrid_cbox.w+2,hidegrid_cbox.y+hidegrid_cbox.h/2-text_height(font)/2,jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1518
1519 bool qgrd = show_quartgrid && qgrid_tool(tool);
1520 gui_textout_ln(screen2,font,(unsigned char*)"Quarter-Grid Draw Modes", reflbtn_grid.x, reflbtn_grid.y-text_height(font)-4,jwin_pal[jcBOXFG],jwin_pal[jcBOX],qgrd?0:D_DISABLED);
1521 for(int q = 0; q < REFL_MAX; ++q)
1522 {
1523 auto& sqr = reflbtn_grid.subsquare(q);
1524 draw_text_button(screen2,sqr.x,sqr.y,sqr.w,sqr.h,reflbtn_names[q],vc(1),vc(14),qgrd ? ((refl_flags&(1<<q)) ? D_SELECTED : 0) : D_DISABLED,true);
1525 }
1526 gui_textout_ln(screen2,font,(unsigned char*)"Transparent Mode", xmodebtn_grid.x, xmodebtn_grid.y-text_height(font)-4,jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1527 for(int q = 0; q < XMODE_MAX; ++q)
1528 {
1529 auto& sqr = xmodebtn_grid.subsquare(q);
1530 draw_text_button(screen2,sqr.x,sqr.y,sqr.w,sqr.h,xmodebtn_names[q],vc(1),vc(14),(xmode == q) ? D_SELECTED : 0,true);
1531 }
1532 for(int q = 0; q < BGMODE_MAX; ++q)
1533 {
1534 auto& sqr = bgmodebtn_grid.subsquare(q);
1535 draw_text_button(screen2,sqr.x,sqr.y,sqr.w,sqr.h,bgmodebtn_names[q],vc(1),vc(14),(bgmode == q) ? D_SELECTED : 0,true);
1536 }
1537
1538 //tool buttons
1539 for(int32_t toolbtn = 0; toolbtn < t_max; ++toolbtn)
1540 {
1541 auto bmp = toolbtn+MOUSE_BMP_SWORD;
1542 int col = toolbtn%tool_btns.w;
1543 int row = toolbtn/tool_btns.w;
1544
1545 jwin_draw_button(screen2,tool_btns.x+(col*tool_btns.xscale),tool_btns.y+(row*tool_btns.yscale),tool_btns.xscale,tool_btns.yscale,tool==toolbtn?2:0,0);
1546 masked_stretch_blit(mouse_bmp_1x[bmp][0],screen2,0,0,16,16,tool_btns.x+(col*tool_btns.xscale)+3+(tool==toolbtn?1:0),tool_btns.y+3+(row*tool_btns.yscale)+(tool==toolbtn?1:0),tool_btns.xscale-7,tool_btns.yscale-7);
1547 }
1548
1549 //coordinates
1550 {
1551 auto mx = gui_mouse_x();
1552 auto my = gui_mouse_y();
1553 int32_t ind = zoomtile.rectind(mx,my);
1554 int32_t temp_x=ind%zoomtile.w;
1555 int32_t temp_y=ind/zoomtile.w;
1556 int color = -1;
1557
1558 bool is8b = newtilebuf[tile].format > tf4Bit;
1559 if(ind > -1)
1560 {
1561 char xbuf[16];
1562 sprintf(xbuf, "x: %d", temp_x);
1563 textprintf_ex(screen2,font,status_info.x,status_info.y+(3*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%s",xbuf);
1564 textprintf_ex(screen2,font,status_info.x+text_length(font,xbuf)+8,status_info.y+(3*status_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"y: %d",temp_y);
1565 unpack_tile(newtilebuf, tile, 0, false);
1566 byte *si = unpackbuf;
1567 si+=ind;
1568 color = *si;
1569 }
1570 else if(fg_prev.rect(mx,my))
1571 color = c1;
1572 else if(bg_prev.rect(mx,my))
1573 color = c2;
1574 else color = (is8b ? cpalette_8 : cpalette_4).rectind(mx,my);
1575 if(color > -1)
1576 {
1577 get_palette(tpal);
1578 char separator = ' ';
1579 char buf[512] = {0};
1580
1581 int realcol = color+(is8b?0:CSET(cs));
1582 bool xcolor = (is8b ? realcol == 0 : (realcol%16)==0);
1583 auto& c = tpal[realcol];
1584
1585 if(tthighlight)
1586 {
1587 size_and_pos const& mainsqr = is8b ? cpalette_8 : cpalette_4;
1588 size_and_pos const& csqr = mainsqr.subsquare(color);
1589
1590 int hlcol = getHighlightColor(tpal[realcol]);
1591 int hlthick = 4;
1592 int extraborder = is8b ? 8 : 0;
1593 int borderthick = hlthick+extraborder;
1594
1595 if(is8b)
1596 {
1597 highlight_sqr(screen2, 0xED, csqr.x, mainsqr.y, csqr.w, mainsqr.h*mainsqr.yscale, hlthick); //column
1598 highlight_sqr(screen2, 0xED, mainsqr.x, csqr.y, mainsqr.w*mainsqr.xscale, csqr.h, hlthick); //row
1599 }
1600 highlight_sqr(screen2, 0xED, csqr.x-borderthick, csqr.y-borderthick, csqr.w+borderthick*2, csqr.h+borderthick*2, hlthick); //square hl
1601 rectfill(screen2, csqr.x-extraborder, csqr.y-extraborder, csqr.x+csqr.w-1+extraborder, csqr.y+csqr.h-1+extraborder, realcol); //square color
1602 if(xcolor)
1603 little_x(screen2, csqr.x-extraborder+4, csqr.y-extraborder+4, invcol, csqr.w+(extraborder*2)-8, csqr.h+(extraborder*2)-8); //transparent X
1604 highlight_sqr(screen2, hlcol, csqr.x-extraborder, csqr.y-extraborder, csqr.w+extraborder*2, csqr.h+extraborder*2, 1); //highlight border
1605 }
1606
1607 sprintf(buf, "%02d %02d %02d %c(0x%02X %d)",c.r,c.g,c.b,separator,realcol,color);
1608 gui_textout_ln(screen2,font,(unsigned char*)buf,hover_info.x,hover_info.y+(2*hover_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1609
1610 strcpy(buf, get_color_name(realcol, is8b).c_str());
1611 gui_textout_ln(screen2,font,(unsigned char*)buf,hover_info.x,hover_info.y+(1*hover_info.yscale),jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1612
1613 sprintf(buf, "#%02X%02X%02X", tpal[realcol].r,tpal[realcol].g,tpal[realcol].b);
1614 gui_textout_ln(screen2,font,(unsigned char*)buf,hover_info.x,hover_info.y+(0),jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
1615
1616 rect(screen2, hov_prev.x, hov_prev.y, hov_prev.x+hov_prev.w-1, hov_prev.y+hov_prev.h-1, jwin_pal[jcTEXTFG]);
1617 rectfill(screen2, hov_prev.x+1, hov_prev.y+1, hov_prev.x+hov_prev.w-2, hov_prev.y+hov_prev.h-2, jwin_pal[jcTEXTBG]);
1618 rectfill(screen2, hov_prev.x+3, hov_prev.y+3, hov_prev.x+hov_prev.w-4, hov_prev.y+hov_prev.h-4, realcol);
1619 if(xcolor)
1620 little_x(screen2, hov_prev.x+1, hov_prev.y+1, invcol, hov_prev.w-2, hov_prev.h-2);
1621 }
1622 }
1623
1624 custom_vsync();
1625 blit(screen2,screen,0,0,0,0,zq_screen_w,zq_screen_w);
1626 update_tool_cursor();
1627 SCRFIX();
1628 }
1629
1630 void normalize(int32_t tile,int32_t tile2, bool rect_sel, int32_t flip)
1631 {
1632 unfloat_selection();
1633 if(tile>tile2)
1634 {
1635 zc_swap(tile, tile2);
1636 }
1637
1638 int32_t left=zc_min(TILECOL(tile), TILECOL(tile2));
1639 int32_t columns=zc_max(TILECOL(tile), TILECOL(tile2))-left+1;
1640
1641 int32_t start=tile;
1642 int32_t end=tile2;
1643
1644 // Might have top-right and bottom-left corners selected...
1645 if(rect_sel && TILECOL(tile)>TILECOL(tile2))
1646 {
1647 start=tile-(TILECOL(tile)-TILECOL(tile2));
1648 end=tile2+(TILECOL(tile)-TILECOL(tile2));
1649 }
1650
1651 for(int32_t temptile=start; temptile<=end; temptile++)
1652 {
1653 if(!rect_sel || ((TILECOL(temptile)>=left) && (TILECOL(temptile)<=left+columns-1)))
1654 {
1655 unpack_tile(newtilebuf, temptile, 0, true);
1656
1657 if(flip&1)
1658 {
1659 for(int32_t y=0; y<16; y++)
1660 {
1661 for(int32_t x=0; x<8; x++)
1662 {
1663 zc_swap(unpackbuf[(y<<4)+x],unpackbuf[(y<<4)+15-x]);
1664 }
1665 }
1666 }
1667
1668 if(flip&2)
1669 {
1670 for(int32_t y=0; y<8; y++)
1671 {
1672 for(int32_t x=0; x<16; x++)
1673 {
1674 zc_swap(unpackbuf[(y<<4)+x],unpackbuf[((15-y)<<4)+x]);
1675 }
1676 }
1677 }
1678
1679 pack_tile(newtilebuf,unpackbuf,temptile);
1680 }
1681 }
1682 }
1683
1684 void rotate_tile(int32_t tile, bool backward)
1685 {
1686 unfloat_selection();
1687 unpack_tile(newtilebuf, tile, 0, true);
1688 byte tempunpackbuf[256];
1689 byte tempx, tempy;
1690
1691 for(tempx=0; tempx<16; tempx++)
1692 {
1693 for(tempy=0; tempy<16; tempy++)
1694 {
1695 if(!backward)
1696 {
1697 tempunpackbuf[(tempy<<4)+tempx]=unpackbuf[((15-tempx)<<4)+tempy];
1698 }
1699 else
1700 {
1701 tempunpackbuf[((15-tempx)<<4)+tempy]=unpackbuf[(tempy<<4)+tempx];
1702 }
1703 }
1704 }
1705
1706 pack_tile(newtilebuf,tempunpackbuf,tile);
1707 }
1708
1709 static int32_t undocount=128;
1710 byte undotile[256];
1711
1712 void wrap_tile(int32_t tile, int32_t vertical, int32_t horizontal, bool clear)
1713 {
1714 byte buf[256];
1715
1716 for(int32_t i=0; i<undocount; i++)
1717 {
1718 newtilebuf[tile].data[i]=undotile[i];
1719 }
1720
1721 if(!(horizontal||vertical))
1722 {
1723 return;
1724 }
1725
1726 unpack_tile(newtilebuf, tile, 0, true);
1727
1728 for(int32_t i=0; i<256; i++)
1729 {
1730 auto shift_ind = ((i+horizontal)&0x0F)|((i+(vertical*0x10))&0xF0);
1731 buf[shift_ind] = unpackbuf[i];
1732 }
1733
1734 if(clear)
1735 {
1736 for(int32_t r=0; r<abs(vertical); r++)
1737 {
1738 for(int32_t c=0; c<16; c++)
1739 {
1740 buf[(vertical>0?r:15-r)*16+c]=0;
1741 }
1742 }
1743
1744 for(int32_t r=0; r<16; r++)
1745 {
1746 for(int32_t c=0; c<abs(horizontal); c++)
1747 {
1748 buf[r*16+(horizontal>0?c:15-c)]=0;
1749 }
1750 }
1751 }
1752
1753 pack_tile(newtilebuf,buf,tile);
1754 }
1755
1756 void wrap_sel_tile(int32_t vertical, int32_t horizontal)
1757 {
1758 byte buf[256];
1759
1760 if(!(horizontal||vertical))
1761 {
1762 return;
1763 }
1764
1765 memset(buf,0,256);
1766
1767 for(int32_t i=0; i<256; i++)
1768 {
1769 if(is_in_selection(i%16,i/16))
1770 {
1771 auto shift_ind = ((i+horizontal)&0x0F)|((i+(vertical*0x10))&0xF0);
1772 buf[shift_ind] = floatsel[i];
1773 }
1774 }
1775
1776 memcpy(floatsel,buf,256);
1777 }
1778
1779 void float_selection(int32_t tile, bool clear)
1780 {
1781 if(floating_sel) return;
1782 floating_sel = true;
1783 floating_tile = tile;
1784
1785 unpack_tile(newtilebuf, tile, 0, true);
1786
1787 for(auto q = 0; q < 256; ++q)
1788 {
1789 if(is_in_selection(q%16,q/16))
1790 {
1791 floatsel[q] = unpackbuf[q];
1792 unpackbuf[q] = clear ? 0 : c2;
1793 }
1794 else floatsel[q] = 0;
1795 }
1796
1797 pack_tile(newtilebuf,unpackbuf,tile);
1798 }
1799
1800 void unfloat_selection()
1801 {
1802 if(!floating_sel) return;
1803 floating_sel = false;
1804
1805 unpack_tile(newtilebuf, floating_tile, 0, true);
1806
1807 for(auto q = 0; q < 256; ++q)
1808 {
1809 if(floatsel[q])
1810 {
1811 unpackbuf[q] = floatsel[q];
1812 }
1813 }
1814
1815 pack_tile(newtilebuf,unpackbuf,floating_tile);
1816 floating_tile = -1;
1817 }
1818
1819 void shift_tile_colors(int32_t tile, int32_t amount, bool ignore_transparent)
1820 {
1821 if(floating_sel)
1822 {
1823 for(auto q = 0; q < 256; ++q)
1824 {
1825 if(ignore_transparent && floatsel[q]==0)
1826 continue;
1827 floatsel[q]=wrap(floatsel[q]+amount, 0, newtilebuf[tile].format==tf8Bit ? 0xDF : 0xF);
1828 }
1829 return;
1830 }
1831
1832 byte buf[256];
1833 unpack_tile(newtilebuf, tile, 0, true);
1834
1835 for(int32_t i=0; i<256; i++)
1836 {
1837 buf[i]=unpackbuf[i];
1838
1839 if(!is_in_selection(i&0x0F, (i&0xF0)>>4))
1840 continue;
1841
1842 if(ignore_transparent)
1843 {
1844 if(buf[i]==0)
1845 continue;
1846
1847 buf[i]=wrap(buf[i]+amount, 1, newtilebuf[tile].format==tf8Bit ? 0xDF : 0xF);
1848 }
1849 else // Don't ignore transparent
1850 buf[i]=wrap(buf[i]+amount, 0, newtilebuf[tile].format==tf8Bit ? 0xDF : 0xF);
1851 }
1852
1853 pack_tile(newtilebuf,buf,tile);
1854 }
1855
1856 void clear_selection_grid()
1857 {
1858 unfloat_selection();
1859 for(int32_t x=0; x<18; ++x)
1860 {
1861 for(int32_t y=0; y<18; ++y)
1862 {
1863 selection_grid[x][y]=0;
1864 }
1865 }
1866 }
1867
1868 void invert_selection_grid()
1869 {
1870 unfloat_selection();
1871 for(int32_t x=1; x<17; ++x)
1872 {
1873 for(int32_t y=1; y<17; ++y)
1874 {
1875 selection_grid[x][y]=selection_grid[x][y]?0:1;
1876 }
1877 }
1878 }
1879
1880 void shift_selection_grid(int32_t xoffs, int32_t yoffs)
1881 {
1882 byte local_grid[16][16];
1883 memset(local_grid, 0, sizeof(local_grid));
1884 for(auto x = 0; x < 16; ++x)
1885 {
1886 for(auto y = 0; y < 16; ++y)
1887 {
1888 auto offs_x = (x+xoffs)%16, offs_y = (y+yoffs)%16;
1889 if(offs_x < 0) offs_x = (16 - abs(offs_x));
1890 if(offs_y < 0) offs_y = (16 - abs(offs_y));
1891 local_grid[offs_x][offs_y] = selection_grid[x+1][y+1]?1:0;
1892 }
1893 }
1894 for(auto x = 0; x < 16; ++x)
1895 {
1896 for(auto y = 0; y < 16; ++y)
1897 {
1898 selection_grid[x+1][y+1] = local_grid[x][y]?1:0;
1899 }
1900 }
1901 }
1902
1903 void show_edit_tile_help()
1904 {
1905 InfoDialog("Help: Tile Editor", "Hotkeys:"
1906 "\nF1: This Help Dialog"
1907 "\nEnter: Unfloat Sel / OK | Esc: Unfloat Sel / Cancel"
1908 "\nDelete: Clear Tile/Sel | Ctrl+Delete: Clear Tile"
1909 "\nA: Sel All | D: Unselect Sel | I: Invert Sel"
1910 "\nH/V: Flip | (Shift+)R: Rotate"
1911 "\n+/-: Change CSet | Ctrl +/-: Shift Colors"
1912 "\n(Ctrl+)S: Swap Colors | U/Ctrl+Z: Undo"
1913 "\nF12: Screenshot (whole screen)"
1914 "\nArrows: Shift Pixel | Ctrl+Arrows: Change Tile"
1915 "\nWhen not on Select tools, hold to swap:"
1916 "\nCtrl - Fill | Alt - Grab | Ctrl+Alt - Recolor").show();
1917 }
1918
1919 static int move_origin_x=-1, move_origin_y=-1;
1920 static int prev_x=-1, prev_y=-1;
1921 bool __pixel_draw(int x, int y, int tile, int flip)
1922 {
1923 bool ret = false;
1924 switch(tool)
1925 {
1926 case t_pen:
1927 if(flip&1) x=15-x;
1928
1929 if(flip&2) y=15-y;
1930
1931 if(is_in_selection(x,y))
1932 {
1933 if(floating_sel)
1934 {
1935 floatsel[(y<<4)+x]=(drawing==1)?c1:c2;
1936 }
1937 else
1938 {
1939 unpack_tile(newtilebuf, tile, 0, false);
1940 unpackbuf[((y<<4)+x)]=(drawing==1)?c1:c2;
1941 pack_tile(newtilebuf, unpackbuf,tile);
1942 }
1943 }
1944 break;
1945
1946 case t_fill:
1947 if(is_in_selection(x,y))
1948 {
1949 tile_floodfill(tile,x,y,(drawing==1)?c1:c2);
1950 ret = true;
1951 }
1952 break;
1953
1954 case t_recolor:
1955 if(is_in_selection(x,y))
1956 {
1957 if(floating_sel)
1958 {
1959 tf_u = floatsel[(y<<4)+x];
1960 for(int32_t i=0; i<256; i++)
1961 {
1962 if(is_in_selection(i&15,i>>4))
1963 {
1964 if(floatsel[i]==tf_u)
1965 {
1966 floatsel[i]=(drawing==1)?c1:c2;
1967 }
1968 }
1969 }
1970 }
1971 else
1972 {
1973 unpack_tile(newtilebuf, tile, 0, false);
1974 tf_u = unpackbuf[(y<<4)+x];
1975 if(tf_u != ((drawing==1)?c1:c2))
1976 {
1977 for(int32_t i=0; i<256; i++)
1978 {
1979 if(is_in_selection(i&15,i>>4))
1980 {
1981 if(unpackbuf[i]==tf_u)
1982 {
1983 unpackbuf[i]=(drawing==1)?c1:c2;
1984 }
1985 }
1986 }
1987
1988 pack_tile(newtilebuf, unpackbuf,tile);
1989 }
1990 }
1991 ret = true;
1992 }
1993 break;
1994
1995 case t_eyedropper:
1996 if(floating_sel)
1997 memcpy(unpackbuf, floatsel, 256);
1998 else unpack_tile(newtilebuf, tile, 0, false);
1999
2000 if(gui_mouse_b()&1)
2001 {
2002 c1=unpackbuf[((y<<4)+x)];
2003 }
2004
2005 if(gui_mouse_b()&2)
2006 {
2007 c2=unpackbuf[((y<<4)+x)];
2008 }
2009 break;
2010
2011 case t_move:
2012 if((prev_x!=x)||(prev_y!=y))
2013 {
2014 if(has_selection())
2015 {
2016 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2017 wrap_sel_tile(y-prev_y, x-prev_x);
2018 shift_selection_grid(x-prev_x, y-prev_y);
2019 }
2020 else wrap_tile(tile, y-move_origin_y, x-move_origin_x, drawing==2);
2021 prev_x=x;
2022 prev_y=y;
2023 }
2024 break;
2025
2026 case t_select:
2027 unfloat_selection();
2028 if(flip&1) x=15-x;
2029
2030 if(flip&2) y=15-y;
2031
2032 if(selecting_x1==-1||selecting_y1==-1)
2033 {
2034 selecting_x1=x;
2035 selecting_y1=y;
2036 }
2037 else
2038 {
2039 selecting_x2=x;
2040 selecting_y2=y;
2041 }
2042 break;
2043
2044 case t_wand:
2045 unfloat_selection();
2046 if(flip&1) x=15-x;
2047
2048 if(flip&2) y=15-y;
2049
2050 switch(select_mode)
2051 {
2052 case 0:
2053 clear_selection_grid();
2054 add_color_to_selection(unpackbuf[((y<<4)+x)]);
2055 break;
2056
2057 case 1:
2058 add_color_to_selection(unpackbuf[((y<<4)+x)]);
2059 break;
2060
2061 case 2:
2062 remove_color_from_selection(unpackbuf[((y<<4)+x)]);
2063 break;
2064
2065 case 3:
2066 intersect_color_with_selection(unpackbuf[((y<<4)+x)]);
2067 break;
2068 }
2069
2070 ret = true;
2071 break;
2072 }
2073 return ret;
2074 }
2075 void edit_tile(int32_t tile,int32_t flip,int32_t &cs)
2076 {
2077 popup_zqdialog_start();
2078 FONT* oldfont = font;
2079 font = get_custom_font(CFONT_DLG);
2080 edit_button.h = ok_button.h = cancel_button.h = 12+text_height(font);
2081 status_info.yscale = text_height(font);
2082 status_info.y = 308-(status_info.h*status_info.yscale);
2083 hover_info.yscale = status_info.yscale;
2084 hover_info.y = 338-(hover_info.h*hover_info.yscale);
2085 go();
2086 undocount = tilesize(newtilebuf[tile].format);
2087 clear_selection_grid();
2088 selecting_x1=selecting_x2=selecting_y1=selecting_y2=-1;
2089
2090 tthighlight = zc_get_config("ZQ_GUI","tile_edit_fancyhighlight",1);
2091 showcolortip = zc_get_config("ZQ_GUI","tile_edit_colornames",1);
2092
2093 PALETTE tpal;
2094 byte oldtile[256];
2095
2096 memset(&tpal, 0, sizeof(PALETTE));
2097 memset(oldtile, 0, 256);
2098
2099 for(int32_t i=0; i<undocount; i++)
2100 {
2101 oldtile[i]=undotile[i]=newtilebuf[tile].data[i];
2102 }
2103 byte undoselgrid[16][16];
2104 for(auto x = 0; x < 16; ++x)
2105 for(auto y = 0; y < 16; ++y)
2106 undoselgrid[x][y] = selection_grid[x+1][y+1];
2107 for(auto q = 0; q < 256; ++q)
2108 {
2109 floatsel[q] = 0;
2110 undofloatsel[q] = 0;
2111 floating_sel = false;
2112 undo_is_floatsel = false;
2113 }
2114
2115 int32_t tile_x=-1, tile_y=-1;
2116 int32_t temp_x=-1, temp_y=-1;
2117 bool bdown=false;
2118 int32_t done=0;
2119 drawing=0;
2120 tool_cur = -1;
2121
2122 get_palette(tpal);
2123
2124 if(newtilebuf[tile].format==tf4Bit)
2125 {
2126 invcol=makecol8(255 - tpal[CSET(cs)].r, 255 - tpal[CSET(cs)].g, 255 - tpal[CSET(cs)].b);
2127 }
2128 else
2129 {
2130 invcol=makecol8(255 - tpal[0].r, 255 - tpal[0].g, 255 - tpal[0].b);
2131 }
2132
2133 custom_vsync();
2134 zc_set_palette(tpal);
2135 draw_edit_scr(tile,flip,cs,oldtile, true);
2136
2137 while(gui_mouse_b())
2138 {
2139 /* do nothing */
2140 rest(1);
2141 }
2142
2143 move_origin_x=-1;
2144 move_origin_y=-1;
2145 prev_x=-1;
2146 prev_y=-1;
2147
2148
2149
2150 byte selection_pattern_source[8][8]=
2151 {
2152 {1, 1, 1, 1, 0, 0, 0, 0},
2153 {1, 1, 1, 0, 0, 0, 0, 1},
2154 {1, 1, 0, 0, 0, 0, 1, 1},
2155 {1, 0, 0, 0, 0, 1, 1, 1},
2156 {0, 0, 0, 0, 1, 1, 1, 1},
2157 {0, 0, 0, 1, 1, 1, 1, 0},
2158 {0, 0, 1, 1, 1, 1, 0, 0},
2159 {0, 1, 1, 1, 1, 0, 0, 0},
2160 };
2161
2162 byte selecting_pattern_source[8][8]=
2163 {
2164 {1, 1, 0, 0, 0, 0, 1, 1},
2165 {1, 0, 0, 0, 0, 1, 1, 1},
2166 {0, 0, 0, 0, 1, 1, 1, 1},
2167 {0, 0, 0, 1, 1, 1, 1, 0},
2168 {0, 0, 1, 1, 1, 1, 0, 0},
2169 {0, 1, 1, 1, 1, 0, 0, 0},
2170 {1, 1, 1, 1, 0, 0, 0, 0},
2171 {1, 1, 1, 0, 0, 0, 0, 1},
2172 };
2173
2174 byte intersection_pattern_source[8][8]=
2175 {
2176 {0, 0, 1, 1, 0, 0, 1, 1},
2177 {0, 1, 1, 0, 0, 1, 1, 0},
2178 {1, 1, 0, 0, 1, 1, 0, 0},
2179 {1, 0, 0, 1, 1, 0, 0, 1},
2180 {0, 0, 1, 1, 0, 0, 1, 1},
2181 {0, 1, 1, 0, 0, 1, 1, 0},
2182 {1, 1, 0, 0, 1, 1, 0, 0},
2183 {1, 0, 0, 1, 1, 0, 0, 1},
2184 };
2185
2186 selection_pattern=create_bitmap_ex(8, 8, 8);
2187
2188 for(int32_t x=0; x<8; ++x)
2189 {
2190 for(int32_t y=0; y<8; ++y)
2191 {
2192 selection_pattern->line[y][x]=selection_pattern_source[x][y]?vc(0):vc(15);
2193 }
2194 }
2195
2196 selecting_pattern=create_bitmap_ex(8, 8, 8);
2197
2198 for(int32_t x=0; x<8; ++x)
2199 {
2200 for(int32_t y=0; y<8; ++y)
2201 {
2202 selecting_pattern->line[y][x]=selecting_pattern_source[x][y]?vc(0):vc(15);
2203 }
2204 }
2205
2206 intersection_pattern=create_bitmap_ex(8, 8, 8);
2207
2208 for(int32_t x=0; x<8; ++x)
2209 {
2210 for(int32_t y=0; y<8; ++y)
2211 {
2212 intersection_pattern->line[y][x]=intersection_pattern_source[x][y]?vc(0):vc(15);
2213 }
2214 }
2215
2216 do
2217 {
2218 HANDLE_CLOSE_ZQDLG();
2219 if(exiting_program) break;
2220 int32_t temp_mouse_x=gui_mouse_x();
2221 int32_t temp_mouse_y=gui_mouse_y();
2222 rest(4);
2223 bool redraw=false;
2224 bool did_wand_select=false;
2225
2226 if(keypressed())
2227 {
2228 bool ctrl = CHECK_CTRL_CMD;
2229 int k = readkey()>>8;
2230 switch(k)
2231 {
2232 case KEY_F1:
2233 show_edit_tile_help();
2234 break;
2235 case KEY_ENTER_PAD:
2236 case KEY_ENTER:
2237 if(floating_sel)
2238 unfloat_selection();
2239 else done=2;
2240 break;
2241
2242 case KEY_ESC:
2243 if(floating_sel)
2244 unfloat_selection();
2245 else if(has_selection())
2246 clear_selection_grid();
2247 else done=1;
2248 break;
2249
2250 case KEY_DEL:
2251 {
2252 unpack_tile(newtilebuf, tile, 0, false);
2253 bool all = CHECK_CTRL_CMD || !has_selection();
2254 bool canDel = false;
2255 if(all)
2256 {
2257 //Check all
2258 for(auto q = 0; q < 256; ++q)
2259 if(unpackbuf[q])
2260 {
2261 canDel = true;
2262 break;
2263 }
2264 }
2265 else
2266 {
2267 //Check selection
2268 for(auto x = 0; x < 16; ++x)
2269 for(auto y = 0; y < 16; ++y)
2270 if(is_in_selection(x,y))
2271 if(unpackbuf[(y<<4)+x])
2272 {
2273 canDel = true;
2274 break;
2275 }
2276 }
2277 if(!canDel) break; //don't delete (and thus reset undo) if nothing would change!
2278
2279 for(int32_t i=0; i<undocount; i++)
2280 {
2281 undotile[i]=newtilebuf[tile].data[i];
2282 }
2283 for(auto x = 0; x < 16; ++x)
2284 for(auto y = 0; y < 16; ++y)
2285 undoselgrid[x][y] = selection_grid[x+1][y+1];
2286 for(auto q = 0; q < 256; ++q)
2287 undofloatsel[q] = floatsel[q];
2288 undo_is_floatsel = floating_sel;
2289
2290 if(CHECK_CTRL_CMD || !has_selection())
2291 {
2292 //Delete all
2293 for(auto q = 0; q < 256; ++q)
2294 {
2295 unpackbuf[q] = 0;
2296 floatsel[q] = 0;
2297 }
2298 }
2299 else
2300 {
2301 //Delete selection
2302 for(auto x = 0; x < 16; ++x)
2303 for(auto y = 0; y < 16; ++y)
2304 {
2305 if(floating_sel)
2306 {
2307 floatsel[x+(y<<4)] = 0;
2308 }
2309 else if(is_in_selection(x,y))
2310 {
2311 unpackbuf[(y<<4)+x] = 0;
2312 }
2313 }
2314 }
2315 pack_tile(newtilebuf, unpackbuf, tile);
2316 redraw=true;
2317 }
2318 break;
2319
2320 case KEY_A:
2321 clear_selection_grid();
2322 invert_selection_grid();
2323 redraw=true;
2324 break;
2325
2326 case KEY_D:
2327 clear_selection_grid();
2328 redraw=true;
2329 break;
2330
2331 case KEY_I:
2332 invert_selection_grid();
2333 redraw=true;
2334 break;
2335
2336 case KEY_H:
2337 flip^=1;
2338 normalize(tile,tile,0,flip);
2339 flip=0;
2340 redraw=true;
2341 break;
2342
2343 case KEY_V:
2344 flip^=2;
2345 normalize(tile,tile,0,flip);
2346 flip=0;
2347 redraw=true;
2348 break;
2349
2350 case KEY_F12:
2351 onSnapshot();
2352 break;
2353
2354 case KEY_R:
2355 {
2356 //if(CHECK_CTRL_CMD))
2357 // {
2358 //do_recolor(tile); redraw=true; saved=false;
2359 // }
2360 //else
2361 // {
2362 go_tiles();
2363 rotate_tile(tile,(key[KEY_LSHIFT] || key[KEY_RSHIFT]));
2364 redraw=true;
2365 saved=false;
2366 break;
2367 }
2368
2369 case KEY_EQUALS:
2370 case KEY_PLUS_PAD:
2371 {
2372 if(CHECK_CTRL_CMD ||
2373 key[KEY_ALT] || key[KEY_ALTGR])
2374 {
2375 for(int32_t i=0; i<undocount; i++)
2376 undotile[i]=newtilebuf[tile].data[i];
2377 for(auto x = 0; x < 16; ++x)
2378 for(auto y = 0; y < 16; ++y)
2379 undoselgrid[x][y] = selection_grid[x+1][y+1];
2380 for(auto q = 0; q < 256; ++q)
2381 undofloatsel[q] = floatsel[q];
2382 undo_is_floatsel = floating_sel;
2383
2384 if(key[KEY_ALT] || key[KEY_ALTGR])
2385 shift_tile_colors(tile, 16, false);
2386 else
2387 shift_tile_colors(tile, 1, key[KEY_LSHIFT] || key[KEY_RSHIFT]);
2388 }
2389 else
2390 cs = (cs<13) ? cs+1:0;
2391
2392 redraw=true;
2393 break;
2394 }
2395
2396 case KEY_MINUS:
2397 case KEY_MINUS_PAD:
2398 {
2399 if(CHECK_CTRL_CMD ||
2400 key[KEY_ALT] || key[KEY_ALTGR])
2401 {
2402 for(int32_t i=0; i<undocount; i++)
2403 undotile[i]=newtilebuf[tile].data[i];
2404 for(auto x = 0; x < 16; ++x)
2405 for(auto y = 0; y < 16; ++y)
2406 undoselgrid[x][y] = selection_grid[x+1][y+1];
2407 for(auto q = 0; q < 256; ++q)
2408 undofloatsel[q] = floatsel[q];
2409 undo_is_floatsel = floating_sel;
2410
2411 if(key[KEY_ALT] || key[KEY_ALTGR])
2412 shift_tile_colors(tile, -16, false);
2413 else
2414 shift_tile_colors(tile, -1, key[KEY_LSHIFT] || key[KEY_RSHIFT]);
2415 }
2416 else
2417 cs = (cs>0) ? cs-1:13;
2418
2419 redraw=true;
2420 break;
2421 }
2422
2423 case KEY_SPACE:
2424 gridmode=(gridmode+1)%gm_max;
2425 redraw=true;
2426 break;
2427
2428 case KEY_Z:
2429 if(!ctrl)
2430 break;
2431 //Ctrl+Z == undo
2432 [[fallthrough]];
2433 case KEY_U:
2434 for(int32_t i=0; i<undocount; i++)
2435 zc_swap(undotile[i],newtilebuf[tile].data[i]);
2436
2437 for(auto x = 0; x < 16; ++x)
2438 for(auto y = 0; y < 16; ++y)
2439 zc_swap(selection_grid[x+1][y+1], undoselgrid[x][y]);
2440
2441 for(auto q = 0; q < 256; ++q)
2442 zc_swap(undofloatsel[q], floatsel[q]);
2443 zc_swap(undo_is_floatsel, floating_sel);
2444
2445 redraw=true;
2446 break;
2447
2448 case KEY_S:
2449 if(CHECK_CTRL_CMD)
2450 {
2451 for(int32_t i=0; i<undocount; i++)
2452 {
2453 undotile[i]=newtilebuf[tile].data[i];
2454 }
2455 for(auto x = 0; x < 16; ++x)
2456 for(auto y = 0; y < 16; ++y)
2457 undoselgrid[x][y] = selection_grid[x+1][y+1];
2458 for(auto q = 0; q < 256; ++q)
2459 undofloatsel[q] = floatsel[q];
2460 undo_is_floatsel = floating_sel;
2461
2462 unpack_tile(newtilebuf, tile, 0, false);
2463
2464 if(has_selection())
2465 {
2466 for(int32_t i=0; i<256; i++)
2467 {
2468 if(!is_in_selection(i%16,i/16))
2469 continue;
2470 if(unpackbuf[i]==c1)
2471 {
2472 unpackbuf[i]=c2;
2473 }
2474 else if(unpackbuf[i]==c2)
2475 {
2476 unpackbuf[i]=c1;
2477 }
2478 if(floating_sel)
2479 {
2480 if(floatsel[i]==c1)
2481 {
2482 floatsel[i]=c2;
2483 }
2484 else if(floatsel[i]==c2)
2485 {
2486 floatsel[i]=c1;
2487 }
2488 }
2489 }
2490 }
2491 else
2492 {
2493 for(int32_t i=0; i<256; i++)
2494 {
2495 if(unpackbuf[i]==c1)
2496 {
2497 unpackbuf[i]=c2;
2498 }
2499 else if(unpackbuf[i]==c2)
2500 {
2501 unpackbuf[i]=c1;
2502 }
2503 }
2504 }
2505
2506 pack_tile(newtilebuf, unpackbuf,tile);
2507 }
2508
2509 zc_swap(c1,c2);
2510 redraw=true;
2511 break;
2512
2513 case KEY_UP:
2514 if(CHECK_CTRL_CMD)
2515 {
2516 unfloat_selection();
2517 tile=zc_max(0,tile-TILES_PER_ROW);
2518 undocount = tilesize(newtilebuf[tile].format);
2519
2520 for(int32_t i=0; i<undocount; i++)
2521 {
2522 undotile[i]=newtilebuf[tile].data[i];
2523 oldtile[i]=undotile[i];
2524 }
2525
2526 redraw=true;
2527 }
2528 else
2529 {
2530 for(int32_t i=0; i<undocount; i++)
2531 {
2532 undotile[i]=newtilebuf[tile].data[i];
2533 }
2534 for(auto x = 0; x < 16; ++x)
2535 for(auto y = 0; y < 16; ++y)
2536 undoselgrid[x][y] = selection_grid[x+1][y+1];
2537 for(auto q = 0; q < 256; ++q)
2538 undofloatsel[q] = floatsel[q];
2539 undo_is_floatsel = floating_sel;
2540 if(has_selection())
2541 {
2542 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2543 wrap_sel_tile(-1, 0);
2544 shift_selection_grid(0, -1);
2545 }
2546 else wrap_tile(tile, -1, 0, false);
2547 redraw=true;
2548 }
2549 break;
2550
2551 case KEY_DOWN:
2552 if(CHECK_CTRL_CMD)
2553 {
2554 unfloat_selection();
2555 tile=zc_min(tile+TILES_PER_ROW,NEWMAXTILES-1);
2556 undocount = tilesize(newtilebuf[tile].format);
2557
2558 for(int32_t i=0; i<undocount; i++)
2559 {
2560 undotile[i]=newtilebuf[tile].data[i];
2561 oldtile[i]=undotile[i];
2562 }
2563
2564 redraw=true;
2565 }
2566 else
2567 {
2568 for(int32_t i=0; i<undocount; i++)
2569 {
2570 undotile[i]=newtilebuf[tile].data[i];
2571 }
2572 for(auto x = 0; x < 16; ++x)
2573 for(auto y = 0; y < 16; ++y)
2574 undoselgrid[x][y] = selection_grid[x+1][y+1];
2575 for(auto q = 0; q < 256; ++q)
2576 undofloatsel[q] = floatsel[q];
2577 undo_is_floatsel = floating_sel;
2578 if(has_selection())
2579 {
2580 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2581 wrap_sel_tile(1, 0);
2582 shift_selection_grid(0, 1);
2583 }
2584 else wrap_tile(tile, 1, 0, false);
2585 redraw=true;
2586 }
2587 break;
2588
2589 case KEY_LEFT:
2590 if(CHECK_CTRL_CMD)
2591 {
2592 unfloat_selection();
2593 tile=zc_max(0,tile-1);
2594 undocount = tilesize(newtilebuf[tile].format);
2595
2596 for(int32_t i=0; i<undocount; i++)
2597 {
2598 undotile[i]=newtilebuf[tile].data[i];
2599 oldtile[i]=undotile[i];
2600 }
2601
2602 redraw=true;
2603 }
2604 else
2605 {
2606 for(int32_t i=0; i<undocount; i++)
2607 {
2608 undotile[i]=newtilebuf[tile].data[i];
2609 }
2610 for(auto x = 0; x < 16; ++x)
2611 for(auto y = 0; y < 16; ++y)
2612 undoselgrid[x][y] = selection_grid[x+1][y+1];
2613 for(auto q = 0; q < 256; ++q)
2614 undofloatsel[q] = floatsel[q];
2615 undo_is_floatsel = floating_sel;
2616 if(has_selection())
2617 {
2618 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2619 wrap_sel_tile(0, -1);
2620 shift_selection_grid(-1, 0);
2621 }
2622 else wrap_tile(tile, 0, -1, false);
2623 redraw=true;
2624 }
2625 break;
2626
2627 case KEY_RIGHT:
2628 if(CHECK_CTRL_CMD)
2629 {
2630 unfloat_selection();
2631 tile=zc_min(tile+1, NEWMAXTILES-1);
2632 undocount = tilesize(newtilebuf[tile].format);
2633
2634 for(int32_t i=0; i<undocount; i++)
2635 {
2636 undotile[i]=newtilebuf[tile].data[i];
2637 oldtile[i]=undotile[i];
2638 }
2639
2640 redraw=true;
2641 }
2642 else
2643 {
2644 for(int32_t i=0; i<undocount; i++)
2645 {
2646 undotile[i]=newtilebuf[tile].data[i];
2647 }
2648 for(auto x = 0; x < 16; ++x)
2649 for(auto y = 0; y < 16; ++y)
2650 undoselgrid[x][y] = selection_grid[x+1][y+1];
2651 for(auto q = 0; q < 256; ++q)
2652 undofloatsel[q] = floatsel[q];
2653 undo_is_floatsel = floating_sel;
2654 if(has_selection())
2655 {
2656 float_selection(tile,key[KEY_LSHIFT]||key[KEY_RSHIFT]);
2657 wrap_sel_tile(0, 1);
2658 shift_selection_grid(1, 0);
2659 }
2660 else wrap_tile(tile, 0, 1, false);
2661 redraw=true;
2662 }
2663 break;
2664 case KEY_0: case KEY_1: case KEY_2: case KEY_3:
2665 case KEY_4: case KEY_5: case KEY_6: case KEY_7:
2666 case KEY_8: case KEY_9:
2667 case KEY_0_PAD: case KEY_1_PAD: case KEY_2_PAD: case KEY_3_PAD:
2668 case KEY_4_PAD: case KEY_5_PAD: case KEY_6_PAD: case KEY_7_PAD:
2669 case KEY_8_PAD: case KEY_9_PAD:
2670 {
2671 int t = k - ((k>KEY_9) ? KEY_1_PAD : KEY_1);
2672 if(unsigned(t) < t_max)
2673 {
2674 if(old_tool != -1)
2675 old_tool = t;
2676 else tool = t;
2677 }
2678 break;
2679 }
2680 case KEY_TAB:
2681 {
2682 if(key_shifts & KB_CTRL_CMD_FLAG)
2683 {
2684 xmode = (xmode+1)%XMODE_MAX;
2685 if(!xmode)
2686 bgmode = (bgmode+1)%BGMODE_MAX;
2687 }
2688 else if(key_shifts & KB_SHIFT_FLAG)
2689 hide_grid = !hide_grid;
2690 else show_quartgrid = !show_quartgrid;
2691 redraw = true;
2692 break;
2693 }
2694 }
2695 clear_keybuf();
2696 }
2697
2698 if(!gui_mouse_b())
2699 {
2700 if(is_selecting())
2701 {
2702 unfloat_selection();
2703 int32_t x1=zc_min(selecting_x1,selecting_x2);
2704 int32_t x2=zc_max(selecting_x1,selecting_x2);
2705 int32_t y1=zc_min(selecting_y1,selecting_y2);
2706 int32_t y2=zc_max(selecting_y1,selecting_y2);
2707
2708 if(select_mode==0)
2709 {
2710 clear_selection_grid();
2711 }
2712
2713 for(int32_t x=x1; x<=x2; ++x)
2714 {
2715 for(int32_t y=y1; y<=y2; ++y)
2716 {
2717 selection_grid[x+1][y+1]=((select_mode<2)?(1):(((select_mode==2)?(0):(selection_grid[x+1][y+1]))));
2718 }
2719 }
2720
2721 if(select_mode==3)
2722 {
2723 for(int32_t y=0; y<16; ++y)
2724 {
2725 for(int32_t x=0; x<x1; ++x)
2726 {
2727 selection_grid[x+1][y+1]=0;
2728 }
2729
2730 for(int32_t x=x2+1; x<16; ++x)
2731 {
2732 selection_grid[x+1][y+1]=0;
2733 }
2734 }
2735
2736 for(int32_t x=x1; x<=x2; ++x)
2737 {
2738 for(int32_t y=0; y<y1; ++y)
2739 {
2740 selection_grid[x+1][y+1]=0;
2741 }
2742
2743 for(int32_t y=y2+1; y<16; ++y)
2744 {
2745 selection_grid[x+1][y+1]=0;
2746 }
2747 }
2748 }
2749 }
2750
2751 selecting_x1=selecting_x2=selecting_y1=selecting_y2=-1;
2752 did_wand_select=false;
2753 }
2754
2755 bool alt=(key[KEY_ALT]||key[KEY_ALTGR]);
2756 bool shift=(key[KEY_LSHIFT] || key[KEY_RSHIFT]);
2757 bool ctrl=CHECK_CTRL_CMD;
2758 static int32_t last_tool_val = 0;
2759
2760 if(tool==t_select||tool==t_wand)
2761 {
2762 if(!drawing)
2763 {
2764 int32_t type=0;
2765
2766 if(has_selection())
2767 {
2768 if(shift)
2769 {
2770 type+=1;
2771 }
2772
2773 if(alt)
2774 {
2775 type+=2;
2776 }
2777 }
2778
2779 if(type!=select_mode)
2780 {
2781 select_mode=type;
2782
2783 if(isinRect(temp_mouse_x,temp_mouse_y-(tool==t_fill ? (14) : 0),zoomtile.x,zoomtile.y,zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
2784 set_tool_sprite(tool,type);
2785 }
2786 }
2787 }
2788 else if(alt||ctrl)
2789 {
2790 if(old_tool==-1)
2791 {
2792 old_tool = tool;
2793 tool_cur = -1;
2794 }
2795 if(alt&&ctrl)
2796 tool = t_recolor;
2797 else if(alt)
2798 tool = t_eyedropper;
2799 else tool = t_fill;
2800 }
2801 else if(old_tool!=-1)
2802 {
2803 tool = old_tool;
2804 old_tool = -1;
2805 tool_cur = -1;
2806 redraw = true;
2807 }
2808 if(last_tool_val != tool)
2809 {
2810 redraw = true;
2811 tool_cur = -1;
2812 update_tool_cursor();
2813 last_tool_val = tool;
2814 }
2815
2816 if(!bdown)
2817 {
2818 move_origin_x=prev_x=(temp_mouse_x-zoomtile.x)/zoomtile.xscale;
2819 move_origin_y=prev_y=(temp_mouse_y-zoomtile.y)/zoomtile.yscale;
2820 }
2821
2822 if(gui_mouse_b()==1 && !bdown) //pressed the left mouse button
2823 {
2824 if(isinRect(temp_mouse_x,temp_mouse_y,zoomtile.x,zoomtile.y-(tool==t_fill ? (14) : 0),zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
2825 {
2826 if(tool==t_move || tool==t_fill)
2827 {
2828 set_tool_sprite(tool,1);
2829
2830 move_origin_x=prev_x=(temp_mouse_x-zoomtile.x)/zoomtile.xscale;
2831 move_origin_y=prev_y=(temp_mouse_y-zoomtile.y)/zoomtile.yscale;
2832 }
2833
2834 for(int32_t i=0; i<undocount; i++)
2835 {
2836 undotile[i]=newtilebuf[tile].data[i];
2837 }
2838 for(auto x = 0; x < 16; ++x)
2839 for(auto y = 0; y < 16; ++y)
2840 undoselgrid[x][y] = selection_grid[x+1][y+1];
2841 for(auto q = 0; q < 256; ++q)
2842 undofloatsel[q] = floatsel[q];
2843 undo_is_floatsel = floating_sel;
2844
2845 drawing=1;
2846 }
2847
2848 if(ok_button.rect(temp_mouse_x,temp_mouse_y))
2849 {
2850 if(do_text_button(ok_button.x,ok_button.y,ok_button.w,ok_button.h,"OK"))
2851 {
2852 done=2;
2853 }
2854 }
2855
2856 if(cancel_button.rect(temp_mouse_x,temp_mouse_y))
2857 {
2858 if(do_text_button(cancel_button.x,cancel_button.y,cancel_button.w,cancel_button.h,"Cancel"))
2859 {
2860 done=1;
2861 }
2862 }
2863
2864 if(edit_button.rect(temp_mouse_x,temp_mouse_y))
2865 {
2866 if(do_text_button(edit_button.x,edit_button.y,edit_button.w,edit_button.h,"Edit Pal"))
2867 {
2868 colors_menu.pop(edit_button.x+2,edit_button.y-40);
2869 get_palette(tpal);
2870
2871 if(newtilebuf[tile].format==tf4Bit)
2872 {
2873 invcol=makecol8(255 - tpal[CSET(cs)].r, 255 - tpal[CSET(cs)].g, 255 - tpal[CSET(cs)].b);
2874 }
2875 else
2876 {
2877 invcol=makecol8(255 - tpal[0].r, 255 - tpal[0].g, 255 - tpal[0].b);
2878 }
2879
2880 redraw=true;
2881 }
2882 }
2883
2884 int sqr_clicked;
2885 if(show_quartgrid && qgrid_tool(tool))
2886 {
2887 sqr_clicked = reflbtn_grid.rectind(temp_mouse_x,temp_mouse_y);
2888 if(sqr_clicked > -1)
2889 {
2890 auto& sqr = reflbtn_grid.subsquare(sqr_clicked);
2891 if(do_text_button(sqr.x,sqr.y,sqr.w,sqr.h,reflbtn_names[sqr_clicked]))
2892 refl_flags ^= (1<<sqr_clicked);
2893 }
2894 }
2895 sqr_clicked = xmodebtn_grid.rectind(temp_mouse_x,temp_mouse_y);
2896 if(sqr_clicked > -1)
2897 {
2898 auto& sqr = xmodebtn_grid.subsquare(sqr_clicked);
2899 if(do_text_button(sqr.x,sqr.y,sqr.w,sqr.h,xmodebtn_names[sqr_clicked]))
2900 xmode = sqr_clicked;
2901 }
2902 sqr_clicked = bgmodebtn_grid.rectind(temp_mouse_x,temp_mouse_y);
2903 if(sqr_clicked > -1)
2904 {
2905 auto& sqr = bgmodebtn_grid.subsquare(sqr_clicked);
2906 if(do_text_button(sqr.x,sqr.y,sqr.w,sqr.h,bgmodebtn_names[sqr_clicked]))
2907 bgmode = sqr_clicked;
2908 }
2909
2910 if(showcolortip)
2911 {
2912 if(color_info.rect(temp_mouse_x,temp_mouse_y))
2913 {
2914 showcolortip = 0;
2915 zc_set_config("ZQ_GUI","tile_edit_colornames",0);
2916 }
2917 }
2918 else
2919 {
2920 if(color_info_btn.rect(temp_mouse_x,temp_mouse_y))
2921 {
2922 if(do_text_button(color_info_btn.x,color_info_btn.y,color_info_btn.w,color_info_btn.h,"Show Colors"))
2923 {
2924 showcolortip = 1;
2925 zc_set_config("ZQ_GUI","tile_edit_colornames",1);
2926 redraw=true;
2927 }
2928 }
2929 }
2930
2931 if(hlcbox.rect(temp_mouse_x,temp_mouse_y))
2932 {
2933 if(do_checkbox(screen2,hlcbox.x,hlcbox.y,hlcbox.w,hlcbox.h,tthighlight))
2934 {
2935 zc_set_config("ZQ_GUI","tile_edit_fancyhighlight",tthighlight);
2936 redraw=true;
2937 }
2938 }
2939 if(quartgrid_cbox.rect(temp_mouse_x,temp_mouse_y))
2940 {
2941 if(do_checkbox(screen2,quartgrid_cbox.x,quartgrid_cbox.y,quartgrid_cbox.w,quartgrid_cbox.h,show_quartgrid))
2942 redraw=true;
2943 }
2944 if(hidegrid_cbox.rect(temp_mouse_x,temp_mouse_y))
2945 {
2946 if(do_checkbox(screen2,hidegrid_cbox.x,hidegrid_cbox.y,hidegrid_cbox.w,hidegrid_cbox.h,hide_grid))
2947 redraw=true;
2948 }
2949
2950 switch(newtilebuf[tile].format)
2951 {
2952 case tf4Bit:
2953 {
2954 auto ind = cpalette_4.rectind(temp_mouse_x,temp_mouse_y);
2955 if(ind > -1)
2956 {
2957 c1 = ind;
2958 redraw=true;
2959 }
2960 break;
2961 }
2962 case tf8Bit:
2963 {
2964 auto ind = cpalette_8.rectind(temp_mouse_x,temp_mouse_y);
2965 if(ind > -1)
2966 {
2967 c1 = ind;
2968 redraw=true;
2969 }
2970 break;
2971 }
2972 }
2973
2974
2975 int32_t newtool = tool_btns.rectind(temp_mouse_x,temp_mouse_y);
2976 if(newtool > -1 && newtool < t_max)
2977 {
2978 tool=newtool;
2979 redraw=true;
2980 }
2981
2982 if(x_btn.rect(temp_mouse_x,temp_mouse_y))
2983 {
2984 if(do_x_button(screen, x_btn.x, x_btn.y))
2985 {
2986 done=1;
2987 }
2988 }
2989 if(info_btn.rect(temp_mouse_x,temp_mouse_y))
2990 {
2991 if(do_question_button(screen, info_btn.x, info_btn.y))
2992 {
2993 show_edit_tile_help();
2994 }
2995 }
2996
2997 bdown=true;
2998 }
2999
3000 if(gui_mouse_b()&2 && !bdown) //pressed the right mouse button
3001 {
3002 if(isinRect(temp_mouse_x,temp_mouse_y,zoomtile.x,zoomtile.y-(tool==t_fill ? (14) : 0),zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
3003 {
3004 if(tool==t_move || tool==t_fill)
3005 {
3006 set_tool_sprite(tool,1);
3007
3008 move_origin_x=prev_x=(temp_mouse_x-zoomtile.x)/zoomtile.xscale;
3009 move_origin_y=prev_y=(temp_mouse_y-zoomtile.y)/zoomtile.yscale;
3010 }
3011
3012 for(int32_t i=0; i<undocount; i++)
3013 {
3014 undotile[i]=newtilebuf[tile].data[i];
3015 }
3016 for(auto x = 0; x < 16; ++x)
3017 for(auto y = 0; y < 16; ++y)
3018 undoselgrid[x][y] = selection_grid[x+1][y+1];
3019 for(auto q = 0; q < 256; ++q)
3020 undofloatsel[q] = floatsel[q];
3021 undo_is_floatsel = floating_sel;
3022
3023 drawing=2;
3024 }
3025
3026 switch(newtilebuf[tile].format)
3027 {
3028 case tf4Bit:
3029 {
3030 auto ind = cpalette_4.rectind(temp_mouse_x,temp_mouse_y);
3031 if(ind > -1)
3032 {
3033 c2 = ind;
3034 redraw=true;
3035 }
3036 break;
3037 }
3038 case tf8Bit:
3039 {
3040 auto ind = cpalette_8.rectind(temp_mouse_x,temp_mouse_y);
3041 if(ind > -1)
3042 {
3043 c2 = ind;
3044 redraw=true;
3045 }
3046 break;
3047 }
3048 }
3049
3050 bdown=true;
3051 }
3052
3053 if(bdown&&!gui_mouse_b()) //released the buttons
3054 {
3055 if(isinRect(temp_mouse_x,temp_mouse_y,zoomtile.x,zoomtile.y-(tool==t_fill ? (14) : 0),zoomtile.x+(zoomtile.w*zoomtile.xscale)-2,zoomtile.y+(zoomtile.h*zoomtile.yscale)-2-(tool==t_fill ? (14) : 0))) //inside the zoomed tile window
3056 {
3057 if(tool==t_move || tool==t_fill)
3058 {
3059 set_tool_sprite(tool,0);
3060 }
3061 }
3062 }
3063
3064 if(drawing && zoomtile.rect(temp_mouse_x,temp_mouse_y)) //inside the zoomed tile window
3065 {
3066 int32_t ind = zoomtile.rectind(temp_mouse_x,temp_mouse_y);
3067 int32_t x=ind%zoomtile.w;
3068 int32_t y=ind/zoomtile.w;
3069
3070 bool reset_draw = false;
3071
3072 if(__pixel_draw(x,y,tile,flip))
3073 reset_draw = true;
3074 if(show_quartgrid)
3075 {
3076 auto tmp_sel_mode = select_mode;
3077 if(tool == t_wand && select_mode == 0)
3078 select_mode = 1;
3079 if(qgrid_tool(tool))
3080 {
3081 if(refl_flags & (1<<REFL_HFLIP))
3082 if(__pixel_draw(15-x,y,tile,flip))
3083 reset_draw = true;
3084 if(refl_flags & (1<<REFL_VFLIP))
3085 if(__pixel_draw(x,15-y,tile,flip))
3086 reset_draw = true;
3087 //Diagonal flip and 180° rotation are the same!
3088 if(refl_flags & ((1<<REFL_DBLFLIP)|(1<<REFL_180)))
3089 if(__pixel_draw(15-x,15-y,tile,flip))
3090 reset_draw = true;
3091 if(refl_flags & (1<<REFL_90CW))
3092 if(__pixel_draw(15-y,x,tile,flip))
3093 reset_draw = true;
3094 if(refl_flags & (1<<REFL_90CCW))
3095 if(__pixel_draw(y,15-x,tile,flip))
3096 reset_draw = true;
3097 }
3098 select_mode = tmp_sel_mode;
3099 }
3100
3101 if(reset_draw)
3102 drawing = 0;
3103 redraw=true;
3104 }
3105
3106 if(gui_mouse_b()==0)
3107 {
3108 bdown=false;
3109 drawing=0;
3110 }
3111
3112 temp_x=(gui_mouse_x()-zoomtile.x)/zoomtile.xscale;
3113 temp_y=(gui_mouse_y()-zoomtile.y)/zoomtile.yscale;
3114
3115 {
3116 tile_x=temp_x;
3117 tile_y=temp_y;
3118 redraw=true;
3119 }
3120
3121 const char *toolnames[t_max]=
3122 {
3123 "Pen\nDraw Single Pixels", "Fill\nCtrl", "Replace Color\nCtrl+Alt", "Grab Color\nAlt", "Move\nMove Selections", "Select Pixels", "Select Color"
3124 };
3125
3126 int32_t toolbtn = tool_btns.rectind(temp_mouse_x,temp_mouse_y);
3127 if(toolbtn > -1 && toolbtn < t_max)
3128 {
3129 int32_t column = toolbtn%tool_btns.w;
3130 int32_t row = toolbtn/tool_btns.w;
3131
3132 update_tooltip(temp_mouse_x,temp_mouse_y,tool_btns.x+(column*tool_btns.xscale),tool_btns.y+(row*tool_btns.yscale),tool_btns.xscale,tool_btns.yscale, toolnames[toolbtn]);
3133 redraw=true;
3134 }
3135 /* Highlight the hovered pixel? Eh, maybe too much?
3136 int32_t hov_pix = zoomtile.rectind(temp_mouse_x,temp_mouse_y);
3137 if(hov_pix > -1)
3138 {
3139 int32_t column = hov_pix%zoomtile.w;
3140 int32_t row = hov_pix/zoomtile.w;
3141
3142 update_tooltip(temp_mouse_x,temp_mouse_y,zoomtile.x+(column*zoomtile.xscale),zoomtile.y+(row*zoomtile.yscale),zoomtile.xscale,zoomtile.yscale, NULL);
3143 redraw=true;
3144 }*/
3145
3146 if(redraw)
3147 {
3148 custom_vsync();
3149 draw_edit_scr(tile,flip,cs,oldtile, false);
3150 }
3151 else
3152 {
3153 bool hs=has_selection();
3154
3155 if(hs)
3156 {
3157 zoomtile16(screen2,tile,zoomtile.x-1,zoomtile.y-1,cs,flip,zoomtile.xscale);
3158 }
3159
3160 custom_vsync();
3161
3162 if(hs)
3163 {
3164 // blit(screen2, screen, 79, 31, 79, 31, 129, 129);
3165 blit(screen2, screen, zoomtile.x-1,zoomtile.y-1, zoomtile.x-1,zoomtile.y-1, (zoomtile.w*zoomtile.xscale)+1, (zoomtile.h*zoomtile.yscale)+1);
3166 }
3167
3168 update_tool_cursor();
3169 SCRFIX();
3170 }
3171
3172 }
3173 while(!done);
3174
3175 unfloat_selection();
3176 clear_selection_grid();
3177
3178 while(gui_mouse_b())
3179 {
3180 /* do nothing */
3181 rest(1);
3182 }
3183
3184 if(done==1)
3185 {
3186 for(int32_t i=0; i<undocount; i++)
3187 {
3188 newtilebuf[tile].data[i]=oldtile[i];
3189 }
3190 }
3191 else
3192 {
3193 byte *buf = new byte[undocount];
3194
3195 // put back old tile
3196 for(int32_t i=0; i<undocount; i++)
3197 {
3198 buf[i] = newtilebuf[tile].data[i];
3199 newtilebuf[tile].data[i] = oldtile[i];
3200 }
3201
3202 // go
3203 go_tiles();
3204
3205 // replace old tile with new one again
3206 for(int32_t i=0; i<undocount; i++)
3207 {
3208 newtilebuf[tile].data[i] = buf[i];
3209 }
3210
3211 saved=false;
3212
3213 if(buf!=NULL)
3214 {
3215 delete[] buf;
3216 }
3217 }
3218
3219 MouseSprite::set(ZQM_NORMAL);
3220 register_blank_tiles();
3221 register_used_tiles();
3222 clear_tooltip();
3223 comeback();
3224 destroy_bitmap(selection_pattern);
3225 destroy_bitmap(selecting_pattern);
3226 destroy_bitmap(intersection_pattern);
3227 font = oldfont;
3228 popup_zqdialog_end();
3229 }
3230
3231 /* Grab Tile Code */
3232
3233 enum recolorState { rcNone, rc4Bit, rc8Bit };
3234
3235 BITMAP* original_imagebuf_bitmap=NULL;
3236 void *imagebuf=NULL;
3237 int32_t imagebuf_bitmap_scale=0;
3238 #define IMAGEBUF_SCALE (imagebuf_bitmap_scale > 0 ? imagebuf_bitmap_scale : 1.0 / -imagebuf_bitmap_scale)
3239 int32_t imagesize=0;
3240 int32_t tilecount=0;
3241 int32_t imagetype=0;
3242 int32_t imagex,imagey,selx,sely;
3243 int32_t bp=4,grabmode=16,romofs=0,romtilemode=0, romtilecols=8;
3244 bool nesmode=false;
3245 int32_t grabmask=0;
3246 recolorState recolor=rcNone;
3247 PALETTE imagepal;
3248
3249 /* bestfit_color:
3250 * Searches a palette for the color closest to the requested R, G, B value.
3251 */
3252 int32_t bestfit_cset_color(int32_t cs, int32_t r, int32_t g, int32_t b)
3253 {
3254 int32_t bestMatch = 0; // Color with the lowest total difference so far
3255 float bestTotalDiff = 100000; // Total difference between requested color and bestMatch
3256 float bestHighDiff = 100000; // Greatest difference of R, G, B between requested color and bestMatch
3257
3258 for(int32_t i = 0; i < CSET_SIZE; i++)
3259 {
3260 byte *rgbByte;
3261
3262 // This seems to be right...
3263 if(cs==2 || cs==3 || cs==4)
3264 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + (cs-2) + pdFULL) + i) * 3;
3265 else if(cs==9)
3266 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + 3 + pdFULL) + i) * 3;
3267 else if(cs==1&&get_qr(qr_CSET1_LEVEL))
3268 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS) + i) * 3;
3269 else if(cs==5&&get_qr(qr_CSET5_LEVEL))
3270 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 1) + i) * 3;
3271 else if(cs==7&&get_qr(qr_CSET7_LEVEL))
3272 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 2) + i) * 3;
3273 else if(cs==8&&get_qr(qr_CSET8_LEVEL))
3274 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 3) + i) * 3;
3275 else
3276 rgbByte = colordata + (CSET(cs)+i)*3;
3277
3278 int32_t dr=r-*rgbByte;
3279 int32_t dg=g-*(rgbByte+1);
3280 int32_t db=b-*(rgbByte+2);
3281
3282 // Track both the total color difference and the single greatest
3283 // difference of R, G, B. The idea is that it's better to have
3284 // two or three small differences than one big one.
3285 // The differences are multiplied by different numbers to account
3286 // for the differences in perceived brightness of the three colors.
3287 float totalDiff = sqrt(dr*dr*0.241 + dg*dg*0.691 + db*db*0.068);
3288 float highDiff = zc_max(zc_max(sqrt(dr*dr*0.241), sqrt(dg*dg*0.691)), sqrt(db*db*0.068));
3289
3290 // Perfect match? Just stop here.
3291 if(totalDiff==0)
3292 return i;
3293
3294 if(totalDiff < bestTotalDiff || // Best match so far?
3295 (totalDiff == bestTotalDiff && highDiff < bestHighDiff)) // Equally good match with lower high difference?
3296 {
3297 bestMatch=i;
3298 bestTotalDiff=totalDiff;
3299 bestHighDiff=highDiff;
3300 }
3301 }
3302
3303 return bestMatch;
3304 }
3305
3306 // Same as the above, but draws from all colors in CSets 0-11.
3307 int32_t bestfit_cset_color_8bit(int32_t r, int32_t g, int32_t b)
3308 {
3309 int32_t bestMatch = 0;
3310 float bestTotalDiff = 100000;
3311 float bestHighDiff = 100000;
3312
3313 for(int32_t i = 0; i < 192; i++) // 192 colors in CSets 0-11
3314 {
3315 byte *rgbByte;
3316
3317 int32_t cs=i>>4;
3318 if(cs==2 || cs==3 || cs==4)
3319 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + (cs-2) + pdFULL) + (i%16)) * 3;
3320 else if(cs==9)
3321 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + 3 + pdFULL) + (i%16)) * 3;
3322 else if(cs==1&&get_qr(qr_CSET1_LEVEL))
3323 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS) + (i%16)) * 3;
3324 else if(cs==5&&get_qr(qr_CSET5_LEVEL))
3325 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 1) + (i%16)) * 3;
3326 else if(cs==7&&get_qr(qr_CSET7_LEVEL))
3327 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 2) + (i%16)) * 3;
3328 else if(cs==8&&get_qr(qr_CSET8_LEVEL))
3329 rgbByte = colordata + (CSET((Map.CurrScr()->color) * pdLEVEL + poNEWCSETS + 3) + (i%16)) * 3;
3330 else
3331 rgbByte = colordata + i * 3;
3332
3333 int32_t dr=r-*rgbByte;
3334 int32_t dg=g-*(rgbByte+1);
3335 int32_t db=b-*(rgbByte+2);
3336
3337 float totalDiff = sqrt(dr*dr*0.241 + dg*dg*0.691 + db*db*0.068);
3338 float highDiff = zc_max(zc_max(sqrt(dr*dr*0.241), sqrt(dg*dg*0.691)), sqrt(db*db*0.068));
3339
3340 if(totalDiff==0) // Perfect match?
3341 return i;
3342
3343 if(totalDiff < bestTotalDiff || // Best match so far?
3344 (totalDiff == bestTotalDiff && highDiff < bestHighDiff)) // Equally good match with lower high difference?
3345 {
3346 bestMatch=i;
3347 bestTotalDiff=totalDiff;
3348 bestHighDiff=highDiff;
3349 }
3350 }
3351
3352 return bestMatch;
3353 }
3354
3355 byte cset_reduce_table[PAL_SIZE];
3356
3357 void calc_cset_reduce_table(PALETTE pal, int32_t cs)
3358 {
3359 for(int32_t i=0; i<PAL_SIZE; i++)
3360 {
3361 cset_reduce_table[i]=(bestfit_cset_color(cs, pal[i].r, pal[i].g, pal[i].b)&0x0F);
3362 }
3363 }
3364
3365 void calc_cset_reduce_table_8bit(PALETTE pal)
3366 {
3367 for(int32_t i=0; i<PAL_SIZE; i++)
3368 {
3369 cset_reduce_table[i]=bestfit_cset_color_8bit(pal[i].r, pal[i].g, pal[i].b);
3370 }
3371 }
3372
3373 void puttileROM(BITMAP *dest,int32_t x,int32_t y,byte *src,int32_t cs)
3374 {
3375 //storage space for the grabbed image
3376 byte buf[64];
3377 memset(buf,0,64);
3378 byte *oldsrc=src;
3379
3380 //for 8 lines in the source image...
3381 for(int32_t line=0; line<(nesmode?4:8); line++)
3382 {
3383 //bx is the pixel at the start of a line in the storage buffer
3384 int32_t bx=line<<(nesmode?4:3);
3385 //b is a byte in the source image (either an entire line in 1bp or the start of a line in others)
3386 byte b=src[(bp&1)?line:line<<1];
3387
3388 //fill the storage buffer with data from the source image
3389 for(int32_t i=7; i>=0; --i)
3390 {
3391 buf[bx+i] = (b&1)+(cs<<4);
3392 b>>=1;
3393 }
3394 }
3395
3396 ++src;
3397
3398 for(int32_t p=1; p<bp; p++)
3399 {
3400 for(int32_t line=0; line<(nesmode?4:8); line++)
3401 {
3402 int32_t bx=line<<(nesmode?4:3);
3403 byte b=src[(bp&1)?line:line<<1];
3404
3405 for(int32_t i=7; i>=0; --i)
3406 {
3407 if(nesmode)
3408 {
3409 buf[bx+8+i] = (b&1)+(cs<<4);
3410 }
3411 else
3412 {
3413 buf[bx+i] |= (b&1)<<p;
3414 }
3415
3416 b>>=1;
3417 }
3418 }
3419
3420 if(p&1)
3421 {
3422 src+=15;
3423 }
3424 else
3425 {
3426 ++src;
3427 }
3428 }
3429
3430
3431 if(nesmode)
3432 {
3433 src=oldsrc;
3434
3435 for(int32_t counter=0; counter<2; ++counter, ++src)
3436 {
3437 //for 8 lines in the source image...
3438 for(int32_t line=0; line<4; line++)
3439 {
3440 //bx is the pixel at the start of a line in the storage buffer
3441 int32_t bx=line<<4;
3442 //b is a byte in the source image (either an entire line in 1bp or the start of a line in others)
3443 byte b=src[(line+4)<<1];
3444
3445 //fill the storage buffer with data from the source image
3446 for(int32_t i=7; i>=0; --i)
3447 {
3448 // buf[bx+i] = (b&1)+(cs<<4);
3449 buf[bx+(counter<<3)+i] |= (b&1)<<1;
3450 b>>=1;
3451 }
3452 }
3453 }
3454 }
3455
3456 int32_t c=0;
3457
3458 switch(romtilemode)
3459 {
3460 case 0:
3461 case 1:
3462 case 2:
3463 for(int32_t j=0; j<8; j++)
3464 {
3465 for(int32_t i=0; i<8; i++)
3466 {
3467 putpixel(dest,x+i,y+j,buf[c++]);
3468 }
3469 }
3470
3471 break;
3472
3473 case 3:
3474 for(int32_t j=0; j<4; j++)
3475 {
3476 for(int32_t i=0; i<16; i++)
3477 {
3478 putpixel(dest,x+i,y+j,buf[c++]);
3479 }
3480 }
3481
3482 break;
3483 }
3484 }
3485
3486 const char *file_type[ftMAX]=
3487 {
3488 "None", "BIN", "BMP", "TIL", "ZGP", "QSU", "ZQT", "QST"
3489 };
3490
3491 void draw_grab_window()
3492 {
3493 int w = 640;
3494 int h = 480;
3495 int window_xofs=0;//(zq_screen_w-w-12)>>1;
3496 int window_yofs=0;//(zq_screen_h-h-25-6)>>1;
3497 jwin_draw_win(screen, window_xofs, window_yofs, w+6+6, h+25+6, FR_WIN);
3498 jwin_draw_frame(screen, window_xofs+4, window_yofs+23, w+2+2, h+2+2-(79*2), FR_DEEP);
3499
3500 FONT *oldfont = font;
3501 font = get_zc_font(font_lfont);
3502 jwin_draw_titlebar(screen, window_xofs+3, window_yofs+3, w+6, 18, "Grab Tile(s)", true);
3503 font=oldfont;
3504 }
3505
3506 void draw_grab_scr(int32_t tile,int32_t cs,byte *newtile,int32_t black,int32_t white, int32_t width, int32_t height, byte *newformat)
3507 {
3508 width=width;
3509 height=height;
3510 white=white; // happy birthday compiler
3511
3512 int32_t yofs=0;
3513 //clear_to_color(screen2,bg);
3514 rectfill(screen2, 0, 0, 319, 159, black);
3515 rectfill(screen2,0,162,319,239,jwin_pal[jcBOX]);
3516 hline(screen2, 0, 160, 319, jwin_pal[jcMEDLT]);
3517 hline(screen2, 0, 161, 319, jwin_pal[jcLIGHT]);
3518 yofs=3;
3519
3520 // text_mode(-1);
3521 int32_t tileromcolumns=20;
3522
3523 switch(imagetype)
3524 {
3525 case ftBMP:
3526 if(recolor==rcNone)
3527 {
3528 blit((BITMAP*)imagebuf,screen2,imagex<<4,imagey<<4,0,0,320,160);
3529 }
3530 else
3531 {
3532 int32_t maxy=zc_min(160,((BITMAP*)imagebuf)->h);
3533 int32_t maxx=zc_min(320,((BITMAP*)imagebuf)->w);
3534
3535 for(int32_t y=0; y<maxy; y++)
3536 {
3537 if((imagey<<4)+y>=((BITMAP*)imagebuf)->h)
3538 {
3539 break;
3540 }
3541
3542 for(int32_t x=0; x<maxx; x++)
3543 {
3544 if((imagex<<4)+x>=((BITMAP*)imagebuf)->w)
3545 {
3546 break;
3547 }
3548
3549 if(recolor==rc8Bit)
3550 screen2->line[y][x]=cset_reduce_table[((BITMAP*)imagebuf)->line[(imagey<<4)+y][(imagex<<4)+x]];
3551 else
3552 screen2->line[y][x]=(cset_reduce_table[((BITMAP*)imagebuf)->line[(imagey<<4)+y][(imagex<<4)+x]])+(cs<<4);
3553 }
3554 }
3555 }
3556
3557 break;
3558
3559 case ftZGP:
3560 case ftQST:
3561 case ftZQT:
3562 case ftQSU:
3563 case ftTIL:
3564 {
3565 tiledata *hold = newtilebuf;
3566 newtilebuf = grabtilebuf;
3567 //fixme
3568 imagey = vbound(imagey, 0, MAXTILEROWS); //fixed -Z This can no longer crash if you scroll past the end of the tile pages. 6th June, 2020
3569 int32_t t=imagey*TILES_PER_ROW;
3570
3571 for(int32_t i=0; i<200; i++) // 10 rows, down to y=160
3572 {
3573 if(t <= tilecount)
3574 {
3575 puttile16(screen2,t,(i%TILES_PER_ROW)<<4,(i/TILES_PER_ROW)<<4,cs,0);
3576 }
3577
3578 ++t;
3579 }
3580
3581 newtilebuf = hold;
3582 //fixme
3583 }
3584 break;
3585
3586 case ftBIN:
3587 {
3588 int32_t ofs = (tileromcolumns*imagex + imagey) * 128*bp + romofs;
3589 byte *buf = (byte*)imagebuf;
3590
3591 switch(romtilemode)
3592 {
3593 case 0:
3594 for(int32_t y=0; y<160; y+=8)
3595 {
3596 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=8)
3597 {
3598 puttileROM(screen2,x,y,buf+ofs,cs);
3599 ofs+=8*bp;
3600 }
3601 }
3602
3603 for(int32_t y=0; y<160; y+=8)
3604 {
3605 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=8)
3606 {
3607 puttileROM(screen2,x+128,y,buf+ofs,cs);
3608 ofs+=8*bp;
3609 }
3610 }
3611
3612 break;
3613
3614 case 1:
3615 for(int32_t y=0; y<160; y+=16)
3616 {
3617 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=8)
3618 {
3619 puttileROM(screen2,x,y,buf+ofs,cs);
3620 ofs+=8*bp;
3621 puttileROM(screen2,x,y+8,buf+ofs,cs);
3622 ofs+=8*bp;
3623 }
3624 }
3625
3626 for(int32_t y=0; y<160; y+=16)
3627 {
3628 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=8)
3629 {
3630 puttileROM(screen2,x+128,y,buf+ofs,cs);
3631 ofs+=8*bp;
3632 puttileROM(screen2,x+128,y+8,buf+ofs,cs);
3633 ofs+=8*bp;
3634 }
3635 }
3636
3637 break;
3638
3639 case 2:
3640 for(int32_t y=0; y<160; y+=16)
3641 {
3642 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=16)
3643 {
3644 puttileROM(screen2,x,y,buf+ofs,cs);
3645 ofs+=8*bp;
3646 puttileROM(screen2,x+8,y,buf+ofs,cs);
3647 ofs+=8*bp;
3648 puttileROM(screen2,x,y+8,buf+ofs,cs);
3649 ofs+=8*bp;
3650 puttileROM(screen2,x+8,y+8,buf+ofs,cs);
3651 ofs+=8*bp;
3652 }
3653 }
3654
3655 for(int32_t y=0; y<160; y+=16)
3656 {
3657 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=16)
3658 {
3659 puttileROM(screen2,x+128,y,buf+ofs,cs);
3660 ofs+=8*bp;
3661 puttileROM(screen2,x+136,y,buf+ofs,cs);
3662 ofs+=8*bp;
3663 puttileROM(screen2,x+128,y+8,buf+ofs,cs);
3664 ofs+=8*bp;
3665 puttileROM(screen2,x+136,y+8,buf+ofs,cs);
3666 ofs+=8*bp;
3667 }
3668 }
3669
3670 break;
3671
3672 case 3:
3673 for(int32_t y=0; y<160; y+=16)
3674 {
3675 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=16)
3676 {
3677 puttileROM(screen2,x,y,buf+ofs,cs);
3678 ofs+=8*bp;
3679 puttileROM(screen2,x,y+4,buf+ofs,cs);
3680 ofs+=8*bp;
3681 puttileROM(screen2,x,y+8,buf+ofs,cs);
3682 ofs+=8*bp;
3683 puttileROM(screen2,x,y+12,buf+ofs,cs);
3684 ofs+=8*bp;
3685 }
3686 }
3687
3688 for(int32_t y=0; y<160; y+=16)
3689 {
3690 for(int32_t x=0; ((x<128)&&(ofs<=imagesize-8*bp)); x+=16)
3691 {
3692 puttileROM(screen2,x+128,y,buf+ofs,cs);
3693 ofs+=8*bp;
3694 puttileROM(screen2,x+128,y+4,buf+ofs,cs);
3695 ofs+=8*bp;
3696 puttileROM(screen2,x+128,y+8,buf+ofs,cs);
3697 ofs+=8*bp;
3698 puttileROM(screen2,x+128,y+12,buf+ofs,cs);
3699 ofs+=8*bp;
3700 }
3701 }
3702
3703 break;
3704 }
3705 }
3706 break;
3707 }
3708
3709 tiledata hold;
3710 bool holdblank = blank_tile_table[0];
3711
3712 if(is_valid_format(newtilebuf[0].format))
3713 {
3714 hold.format = newtilebuf[0].format;
3715 hold.data = (byte *)malloc(tilesize(hold.format));
3716 memcpy(hold.data, newtilebuf[0].data, tilesize(hold.format));
3717 }
3718 else
3719 {
3720 hold.format=tfInvalid;
3721 hold.data=NULL;
3722 }
3723
3724 newtilebuf[0].format=newformat[0];
3725 blank_tile_table[0] = false;
3726
3727 if(newtilebuf[0].data!=NULL)
3728 {
3729 free(newtilebuf[0].data);
3730 }
3731
3732 if(is_valid_format(newtilebuf[0].format))
3733 {
3734 newtilebuf[0].data = (byte *)malloc(tilesize(newtilebuf[0].format));
3735
3736 for(int32_t i=0; i<tilesize(newtilebuf[0].format); i++)
3737 {
3738 newtilebuf[0].data[i]=newtile[i];
3739 }
3740 }
3741 else
3742 {
3743 newtilebuf[0].data=NULL;
3744 }
3745
3746 puttile16(screen2,0,208,168+yofs,cs,0);
3747 overtile16(screen2,0,232,168+yofs,cs,0);
3748 newtilebuf[0].format=hold.format;
3749 blank_tile_table[0] = holdblank;
3750
3751 if(newtilebuf[0].data!=NULL)
3752 {
3753 free(newtilebuf[0].data);
3754 }
3755
3756 if(is_valid_format(newtilebuf[0].format))
3757 {
3758 newtilebuf[0].data = (byte *)malloc(tilesize(newtilebuf[0].format));
3759
3760 for(int32_t i=0; i<256; i++)
3761 {
3762 newtilebuf[0].data[i]=hold.data[i];
3763 }
3764 }
3765 else
3766 {
3767 newtilebuf[0].data=NULL;
3768 }
3769
3770 if(hold.data!=NULL)
3771 {
3772 free(hold.data);
3773 }
3774
3775 puttile16(screen2,tile,208,192+yofs,cs,0);
3776 overtile16(screen2,tile,232,192+yofs,cs,0);
3777
3778 rectfill(screen2,184,168+yofs,191,175+yofs,grabmask&1?vc(12):vc(7));
3779 rectfill(screen2,192,168+yofs,199,175+yofs,grabmask&2?vc(12):vc(7));
3780 rectfill(screen2,184,176+yofs,191,183+yofs,grabmask&4?vc(12):vc(7));
3781 rectfill(screen2,192,176+yofs,199,183+yofs,grabmask&8?vc(12):vc(7));
3782
3783 // rect(screen2,183,167,200,184,dvc(7*2));
3784 // rect(screen2,207,167,224,184,dvc(7*2));
3785 // rect(screen2,231,167,248,184,dvc(7*2));
3786 // rect(screen2,207,191,224,208,dvc(7*2));
3787 // rect(screen2,231,191,248,208,dvc(7*2));
3788
3789 /*
3790 rect(screen2,183,167,200,184,vc(14));
3791 rect(screen2,207,167,224,184,vc(14));
3792 rect(screen2,231,167,248,184,vc(14));
3793 rect(screen2,207,191,224,208,vc(14));
3794 rect(screen2,231,191,248,208,vc(14));
3795 */
3796 jwin_draw_frame(screen2,182,166+yofs,20,20,FR_DEEP);
3797 jwin_draw_frame(screen2,206,166+yofs,20,20,FR_DEEP);
3798 jwin_draw_frame(screen2,230,166+yofs,20,20,FR_DEEP);
3799 jwin_draw_frame(screen2,206,190+yofs,20,20,FR_DEEP);
3800 jwin_draw_frame(screen2,230,190+yofs,20,20,FR_DEEP);
3801 int32_t screen_xofs=6;
3802 int32_t screen_yofs=25;
3803 int winh = 511;
3804 int32_t mul = 2;
3805
3806 yofs=16;
3807
3808 custom_vsync();
3809
3810 stretch_blit(screen2,screen,0,0,320,240,screen_xofs,screen_yofs,640,480);
3811
3812 // Suspend the current font while draw_text_button does its work
3813 FONT* oldfont = font;
3814
3815 font = get_zc_font(font_lfont_l);
3816
3817 int txt_x = 8*mul;
3818 int rbtn_x = 255*mul;
3819 int max_fpath_wid = rbtn_x-2-txt_x;
3820 int max_fpath_wid2 = max_fpath_wid-text_length(font,"... ");
3821 // Interface
3822 switch(imagetype)
3823 {
3824 case 0:
3825 textprintf_ex(screen,font,txt_x,(216+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"%s",imgstr[imagetype]);
3826 break;
3827
3828 case ftBMP:
3829 {
3830 std::string text = fmt::format("{} {}x{}, {:.2g}x zoom with , and .", imgstr[imagetype], original_imagebuf_bitmap->w, original_imagebuf_bitmap->h, IMAGEBUF_SCALE);
3831 int text_x = txt_x;
3832 int text_y = (216 + yofs) * mul;
3833 // TODO: can almost use this, but drawing is offset. prob cuz drawing to a different bitmap than the normal screen bitmap? idk
3834 // int text_w = text_length(font, text.c_str());
3835 // int text_h = text_height(font);
3836 // static int grab_scale_tooltip_id = ttip_register_id();
3837 // ttip_install(grab_scale_tooltip_id, "zoom with , and .", text_x, text_y, text_w, text_h, text_x, text_y - 40);
3838 textprintf_ex(screen, font, text_x, text_y, jwin_pal[jcTEXTFG], jwin_pal[jcBOX], "%s", text.c_str());
3839
3840 draw_text_button(screen,117*mul,(192+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"Recolor",vc(1),vc(14),0,true);
3841 break;
3842 }
3843
3844 case ftZGP:
3845 case ftQST:
3846 case ftZQT:
3847 case ftQSU:
3848 case ftTIL:
3849 case ftBIN:
3850 textprintf_ex(screen,get_zc_font(font_lfont_l),txt_x,(216+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"%s %d KB",imgstr[imagetype],imagesize>>10);
3851 break;
3852 }
3853
3854 textprintf_ex(screen,font,txt_x,(168+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"sel: %d %d",selx,sely);
3855 textprintf_ex(screen,font,txt_x,(176+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"pos: %d %d",imagex,imagey);
3856
3857 if(bp==8)
3858 textprintf_ex(screen,font,txt_x,(192+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"8-bit");
3859 else
3860 textprintf_ex(screen,font,txt_x,(192+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"cset: %d",cs);
3861 textprintf_ex(screen,font,txt_x,(200+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"step: %d",grabmode);
3862
3863 if(imagetype==ftBIN)
3864 {
3865 textprintf_ex(screen,font,104*mul,(192+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"bp: %d%s",bp,nesmode?" (NES)":"");
3866 textprintf_ex(screen,font,104*mul,(200+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"ofs: %Xh",romofs);
3867 textprintf_ex(screen,font,104*mul,(208+yofs)*mul,jwin_pal[jcTEXTFG],jwin_pal[jcBOX],"m: %d",romtilemode);
3868 }
3869
3870 int fpath_y = (224+yofs)*mul;
3871 if(text_length(font,imagepath) <= max_fpath_wid)
3872 textout_ex(screen,font,imagepath,txt_x,fpath_y,jwin_pal[jcTEXTFG],jwin_pal[jcBOX]);
3873 else
3874 {
3875 char buf[2052] = {0};
3876 strncpy(buf,imagepath,2048);
3877 int len = strlen(buf);
3878 char *ptr = buf;
3879 char *endptr = buf+len;
3880 char *it = endptr;
3881 int tmpy = fpath_y;
3882 int tmph = text_height(font)+1;
3883 while(true)
3884 {
3885 if(tmpy+tmph > (winh-2))
3886 break; //Out of space!
3887 char c = *it;
3888 bool end = !c;
3889 *it = 0;
3890 int newlen = text_length(font,ptr);
3891 if(newlen <= (end ? max_fpath_wid : max_fpath_wid2))
3892 {
3893 if(end) //No stored character, string ended
3894 {
3895 textout_ex(screen,font,ptr,txt_x,tmpy,jwin_pal[jcTEXTFG],jwin_pal[jcBOX]);
3896 break;
3897 }
3898 char t[5];
3899 t[0] = c;
3900 for(int q = 1; q < 5; ++q)
3901 t[q] = it[q];
3902 strcpy(it,"...");
3903 textout_ex(screen,font,ptr,txt_x,tmpy,jwin_pal[jcTEXTFG],jwin_pal[jcBOX]);
3904 for(int q = 0; q < 5; ++q)
3905 it[q] = t[q];
3906 tmpy += tmph;
3907 ptr = it;
3908 it = endptr;
3909 }
3910 else
3911 {
3912 *it = c;
3913 --it;
3914 }
3915 }
3916 }
3917 draw_text_button(screen,rbtn_x,(168+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"OK",vc(1),vc(14),0,true);
3918 draw_text_button(screen,rbtn_x,(192+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"Cancel",vc(1),vc(14),0,true);
3919 draw_text_button(screen,rbtn_x,(216+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"File",vc(1),vc(14),0,true);
3920 draw_text_button(screen,117*mul,(166+yofs)*mul,int32_t(61*(1.5)),int32_t(20*(1.5)),"Leech",vc(1),vc(14),0,true);
3921
3922 //int32_t rectw = 16*mul;
3923 //rect(screen,selx+screen_xofs,sely+screen_yofs,selx+screen_xofs+((width-1)*rectw)+rectw-1,sely+screen_yofs+((height-1)*rectw)+rectw-1,white);
3924 SCRFIX();
3925 font = oldfont;
3926 }
3927
3928 RGB_MAP rgb_table;
3929 COLOR_MAP imagepal_table;
3930
3931
3932 extern void return_RAMpal_color(AL_CONST PALETTE pal, int32_t x, int32_t y, RGB *rgb)
3933 {
3934 //these are here to bypass compiler warnings about unused arguments
3935 x=x;
3936
3937 rgb->r = pal[y].r;
3938 rgb->g = pal[y].g;
3939 rgb->b = pal[y].b;
3940 }
3941
3942
3943 void load_imagebuf()
3944 {
3945 PACKFILE *f;
3946 //cache QRS
3947 //byte cached_rules[QUESTRULES_NEW_SIZE] = { 0 };
3948 //for ( int32_t q = 0; q < QUESTRULES_NEW_SIZE; ++q )
3949 // {
3950 // cached_rules[q] = quest_rules[q];
3951 // }
3952 bool compressed=false;
3953 bool encrypted=false;
3954 tiledata *hold=newtilebuf;
3955 zquestheader tempheader;
3956 memset(&tempheader, 0, sizeof(zquestheader));
3957
3958 if(imagebuf)
3959 {
3960 switch(imagetype)
3961 {
3962 case ftBMP:
3963 if (original_imagebuf_bitmap != imagebuf)
3964 destroy_bitmap((BITMAP*)imagebuf);
3965 destroy_bitmap(original_imagebuf_bitmap);
3966 break;
3967
3968 case ftZGP:
3969 case ftQST:
3970 case ftZQT:
3971 case ftQSU:
3972 case ftTIL:
3973 clear_tiles(grabtilebuf);
3974 break;
3975
3976 case ftBIN:
3977 free(imagebuf);
3978 break;
3979 }
3980
3981 imagebuf=NULL;
3982 original_imagebuf_bitmap=NULL;
3983 }
3984
3985 selx=sely=romofs=0;
3986 bp=4;
3987 imagetype=filetype(imagepath);
3988
3989 dword section_id;
3990 dword section_version;
3991 dword section_cversion;
3992
3993 switch(imagetype)
3994 {
3995 case ftBMP:
3996 packfile_password("");
3997 memset(imagepal, 0, sizeof(PALETTE));
3998 original_imagebuf_bitmap = load_bitmap(imagepath,imagepal);
3999 imagesize = file_size_ex_password(imagepath,"");
4000 tilecount=0;
4001 create_rgb_table(&rgb_table, imagepal, NULL);
4002 rgb_map = &rgb_table;
4003 create_color_table(&imagepal_table, RAMpal, return_RAMpal_color, NULL);
4004
4005 if(!original_imagebuf_bitmap)
4006 {
4007 imagetype=0;
4008 }
4009 else
4010 {
4011 imagebuf = original_imagebuf_bitmap;
4012 imagebuf_bitmap_scale = 1;
4013 }
4014
4015 break;
4016
4017 case ftBIN:
4018 packfile_password("");
4019 imagesize = file_size_ex_password(imagepath, "");
4020 tilecount=0;
4021
4022 if(imagesize)
4023 {
4024 imagebuf = malloc(imagesize);
4025
4026 if(!readfile(imagepath,imagebuf,imagesize))
4027 {
4028 free(imagebuf);
4029 imagesize=0;
4030 imagetype=0;
4031 }
4032 }
4033
4034 break;
4035
4036 case ftTIL:
4037 packfile_password("");
4038 imagesize = file_size_ex_password(imagepath,"");
4039 f = pack_fopen_password(imagepath,F_READ,"");
4040
4041 if(!f)
4042 {
4043 goto error;
4044 }
4045
4046 if(!p_mgetl(&section_id,f))
4047 {
4048 goto error;
4049 }
4050
4051 if(section_id==ID_TILES)
4052 {
4053 if(readtiles(f, grabtilebuf, NULL, ZELDA_VERSION, VERSION_BUILD, 0, NEWMAXTILES, false)==0)
4054 {
4055 goto error;
4056 }
4057 }
4058
4059 error:
4060 pack_fclose(f);
4061 tilecount=count_tiles(grabtilebuf);
4062 break;
4063
4064 case ftZGP:
4065 packfile_password("");
4066 imagesize = file_size_ex_password(imagepath, "");
4067 f=pack_fopen_password(imagepath,F_READ,"");
4068
4069 if(!f)
4070 {
4071 goto error2;
4072 }
4073
4074 if(!p_mgetl(&section_id,f))
4075 {
4076 goto error2;
4077 }
4078
4079 if(section_id!=ID_GRAPHICSPACK)
4080 {
4081 goto error2;
4082 }
4083
4084 //section version info
4085 if(!p_igetw(&section_version,f))
4086 {
4087 goto error2;
4088 }
4089
4090 if(!p_igetw(&section_cversion,f))
4091 {
4092 goto error2;
4093 }
4094
4095 //tiles
4096 if(!p_mgetl(&section_id,f))
4097 {
4098 goto error2;
4099 }
4100
4101 if(section_id==ID_TILES)
4102 {
4103 if(readtiles(f, grabtilebuf, NULL, ZELDA_VERSION, VERSION_BUILD, 0, NEWMAXTILES, false)!=0)
4104 {
4105 goto error2;
4106 }
4107 }
4108
4109 error2:
4110 pack_fclose(f);
4111 tilecount=count_tiles(grabtilebuf);
4112 break;
4113
4114 case ftQST:
4115 encrypted=true;
4116 case ftZQT:
4117 compressed=true;
4118 case ftQSU:
4119 packfile_password("");
4120 imagesize = file_size_ex_password(imagepath, encrypted ? datapwd : "");
4121 newtilebuf=grabtilebuf;
4122 byte skip_flags[4];
4123
4124 for(int32_t i=0; i<skip_max; ++i)
4125 {
4126 set_bit(skip_flags,i,1);
4127 }
4128
4129 set_bit(skip_flags,skip_tiles,0);
4130 set_bit(skip_flags,skip_header,0);
4131 int ret = loadquest(imagepath,&tempheader,&QMisc,customtunes,true,skip_flags);
4132 if (ret)
4133 {
4134 imagetype=0;
4135 imagesize=0;
4136 clear_tiles(grabtilebuf);
4137 chop_path(imagepath);
4138 }
4139
4140 if (!ret && encrypted && compressed)
4141 {
4142 if(quest_access(imagepath, &tempheader) != 1)
4143 {
4144 imagetype=0;
4145 imagesize=0;
4146 clear_tiles(grabtilebuf);
4147 chop_path(imagepath);
4148 }
4149 }
4150
4151 //setPackfilePassword(NULL);
4152 newtilebuf=hold;
4153 tilecount=count_tiles(grabtilebuf);
4154 break;
4155 }
4156
4157 rgb_map = &zq_rgb_table;
4158 //restore cashed QRs / rules
4159
4160 //for ( int32_t q = 0; q < QUESTRULES_NEW_SIZE; ++q )
4161 // {
4162 // quest_rules[q] = cached_rules[q];
4163 // }
4164 }
4165
4166 static char bitstrbuf[32];
4167 bool leeching_from_tiles=false;
4168
4169 const char *bitlist(int32_t index, int32_t *list_size)
4170 {
4171 int32_t imported=2;
4172
4173 if(index>=0)
4174 {
4175 bound(index,0,leeching_from_tiles?2:1);
4176
4177 if(index==imported)
4178 {
4179 sprintf(bitstrbuf,"Imported");
4180 }
4181 else
4182 {
4183 sprintf(bitstrbuf,"%d",4<<index);
4184 }
4185
4186 return bitstrbuf;
4187 }
4188
4189 *list_size=leeching_from_tiles?3:2;
4190 return NULL;
4191 }
4192
4193 9 static ListData bit_list(bitlist, &font);
4194
4195 static DIALOG leech_dlg[] =
4196 {
4197 /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */
4198 9 { jwin_win_proc, 8, 20-4, 303+1, 216-42+1, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Leech Options", NULL, NULL },
4199 9 { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
4200 // 2
4201 9 { jwin_button_proc, 180, 210-42-4, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
4202 9 { jwin_button_proc, 80, 210-42-4, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
4203 9 { d_keyboard_proc, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F1, 0, (void *) onHelp, NULL, NULL },
4204 // 5
4205 9 { jwin_text_proc, 14, 49-4, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Update Status Every: ", NULL, NULL },
4206 9 { jwin_edit_proc, 114, 45-4, 36, 16, vc(12), vc(1), 0, 0, 5, 0, NULL, NULL, NULL },
4207 9 { jwin_radio_proc, 155, 49-4, 64+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Tiles", NULL, NULL },
4208 9 { jwin_radio_proc, 200, 49-4, 64+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Seconds", NULL, NULL },
4209 //9
4210 9 { jwin_frame_proc, 14, 63-2, 176+70, 50+30, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, FR_ETCHED, 0, NULL, NULL, NULL },
4211 9 { jwin_text_proc, 14+8, 60-2, 80, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) " Duplicates ", NULL, NULL },
4212
4213 9 { jwin_check_proc, 20, 70, 168, 8+1, vc(15), vc(1), 0, 0, 1, 0, (void *) "Only check new tiles", NULL, NULL },
4214 9 { jwin_text_proc, 20, 90, 72, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Normal:", NULL, NULL },
4215 9 { jwin_text_proc, 20, 100, 72, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Horizontal Flip:", NULL, NULL },
4216 9 { jwin_text_proc, 20, 110, 72, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Vertical Flip:", NULL, NULL },
4217 9 { jwin_text_proc, 20, 120, 72, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Horizontal/Vertical Flip:", NULL, NULL },
4218 //16
4219 9 { jwin_radio_proc, 144, 90, 64+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL },
4220 9 { jwin_radio_proc, 184, 90, 56+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL },
4221 9 { jwin_radio_proc, 224, 90, 72+1, 8+1, vc(14), vc(1), 0, 0, 1, 0, NULL, NULL, NULL },
4222
4223 9 { jwin_radio_proc, 144, 100, 64+1, 8+1, vc(14), vc(1), 0, 0, 2, 0, NULL, NULL, NULL },
4224 9 { jwin_radio_proc, 184, 100, 56+1, 8+1, vc(14), vc(1), 0, 0, 2, 0, NULL, NULL, NULL },
4225 9 { jwin_radio_proc, 224, 100, 72+1, 8+1, vc(14), vc(1), 0, 0, 2, 0, NULL, NULL, NULL },
4226
4227 9 { jwin_radio_proc, 144, 110, 64+1, 8+1, vc(14), vc(1), 0, 0, 3, 0, NULL, NULL, NULL },
4228 9 { jwin_radio_proc, 184, 110, 56+1, 8+1, vc(14), vc(1), 0, 0, 3, 0, NULL, NULL, NULL },
4229 9 { jwin_radio_proc, 224, 110, 72+1, 8+1, vc(14), vc(1), 0, 0, 3, 0, NULL, NULL, NULL },
4230
4231 9 { jwin_radio_proc, 144, 120, 64+1, 8+1, vc(14), vc(1), 0, 0, 4, 0, NULL, NULL, NULL },
4232 9 { jwin_radio_proc, 184, 120, 56+1, 8+1, vc(14), vc(1), 0, 0, 4, 0, NULL, NULL, NULL },
4233 9 { jwin_radio_proc, 224, 120, 72+1, 8+1, vc(14), vc(1), 0, 0, 4, 0, NULL, NULL, NULL },
4234
4235 9 { jwin_ctext_proc, 144+4, 80, 64+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Ignore", NULL, NULL },
4236 9 { jwin_ctext_proc, 184+4, 80, 56+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Check", NULL, NULL },
4237 9 { jwin_ctext_proc, 224+4, 80, 72+1, 8+1, vc(14), vc(1), 0, 0, 0, 0, (void *) "Discard", NULL, NULL },
4238 9 { jwin_droplist_proc, 76, 145, 80, 16, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, 0, 1, 0, (void *) &bit_list, NULL, NULL },
4239 9 { jwin_text_proc, 14, 149, 60, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Color Depth: ", NULL, NULL },
4240 9 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
4241 };
4242
4243 bool leech_tiles(tiledata *dest,int32_t start,int32_t cs)
4244 {
4245 bool shift=true; // fix this!
4246 int32_t cst=0;
4247 int32_t currtile=start;
4248 int32_t height=0, width=0;
4249 byte *testtile = new byte[tilesize(tf32Bit)];
4250 byte imported_format=0;
4251 char updatestring[6];
4252 bool canadd;
4253 bool temp_canadd;
4254 bool duplicate;
4255 int32_t total_duplicates_found=0, total_duplicates_discarded=0;
4256 int32_t duplicates_found[4]= //, duplicates_discarded[4]={0,0,0,0};
4257 {
4258 0,0,0,0
4259 };
4260 BITMAP *status;
4261 status = create_bitmap_ex(8,240,140);
4262 clear_bitmap(status);
4263 sprintf(updatestring, "%d", LeechUpdate);
4264 leech_dlg[0].dp2=get_zc_font(font_lfont);
4265 leech_dlg[6].dp=updatestring;
4266
4267 leech_dlg[10].flags=(OnlyCheckNewTilesForDuplicates!=0) ? D_SELECTED : 0;
4268
4269 for(int32_t i=0; i<2; i++)
4270 {
4271 leech_dlg[i+7].flags=0;
4272 }
4273
4274 leech_dlg[7+((LeechUpdateTiles==0) ? 1 : 0)].flags=D_SELECTED;
4275
4276 for(int32_t i=0; i<12; i++)
4277 {
4278 leech_dlg[i+16].flags=0;
4279 }
4280
4281 for(int32_t i=0; i<4; i++)
4282 {
4283 leech_dlg[(DuplicateAction[i])+16+(i*3)].flags=D_SELECTED;
4284 }
4285
4286 leech_dlg[31].d1=0;
4287
4288 large_dialog(leech_dlg);
4289
4290 int32_t ret = do_zqdialog(leech_dlg,3);
4291
4292 if(ret==2)
4293 {
4294 delete[] testtile;
4295 return false;
4296 }
4297
4298 int32_t cdepth=leech_dlg[31].d1+1;
4299 int32_t newformat=0;
4300 auto lu = atoi(updatestring);
4301 auto lut = (leech_dlg[7].flags&D_SELECTED)?1:0;
4302 if(LeechUpdate!=lu)
4303 {
4304 LeechUpdate=lu;
4305 zc_set_config("zquest","leech_update",LeechUpdate);
4306 }
4307 if(LeechUpdateTiles!=lut)
4308 {
4309 LeechUpdateTiles=lut;
4310 zc_set_config("zquest","leech_update_tiles",LeechUpdateTiles);
4311 }
4312
4313 int32_t old_dupe[4];
4314 for(int32_t j=0; j<4; j++)
4315 {
4316 old_dupe[j] = DuplicateAction[j];
4317 for(int32_t i=0; i<3; i++)
4318 {
4319 if(leech_dlg[i+16+(j*3)].flags&D_SELECTED)
4320 {
4321 DuplicateAction[j]=i;
4322 }
4323 }
4324 }
4325 if(old_dupe[0] != DuplicateAction[0])
4326 zc_set_config("zquest","normal_duplicate_action",DuplicateAction[0]);
4327 if(old_dupe[1] != DuplicateAction[1])
4328 zc_set_config("zquest","horizontal_duplicate_action",DuplicateAction[1]);
4329 if(old_dupe[2] != DuplicateAction[2])
4330 zc_set_config("zquest","vertical_duplicate_action",DuplicateAction[2]);
4331 if(old_dupe[3] != DuplicateAction[3])
4332 zc_set_config("zquest","both_duplicate_action",DuplicateAction[3]);
4333
4334 auto ocntfd = leech_dlg[10].flags&D_SELECTED?1:0;
4335 if(OnlyCheckNewTilesForDuplicates!=ocntfd)
4336 {
4337 OnlyCheckNewTilesForDuplicates=ocntfd;
4338 zc_set_config("zquest","only_check_new_tiles_for_duplicates",ocntfd);
4339 }
4340
4341 leeching_from_tiles=false;
4342
4343 switch(imagetype)
4344 {
4345 case ftBIN:
4346 width=imagesize/128;
4347 height=1;
4348 break;
4349
4350 case ftZGP:
4351 case ftQST:
4352 case ftZQT:
4353 case ftQSU:
4354 case ftTIL:
4355 leeching_from_tiles=true;
4356 width=count_tiles(grabtilebuf);
4357 height=1;
4358 break;
4359
4360 case ftBMP:
4361 width=((((BITMAP*)imagebuf)->w)+15)/16;
4362 height=((((BITMAP*)imagebuf)->h)+15)/16;
4363 break;
4364 }
4365
4366 if(currtile+(width*height)>NEWMAXTILES)
4367 {
4368 if(jwin_alert("Confirm Truncation","Too many tiles.","Truncation may occur.",NULL,"&OK","&Cancel",'o','c',get_zc_font(font_lfont))==2)
4369 {
4370 delete[] testtile;
4371 return false;
4372 }
4373 }
4374
4375 go_tiles();
4376 saved=false;
4377
4378 for(int32_t ty=0; ty<height; ty++) //for every row
4379 {
4380 for(int32_t tx=0; tx<width; tx++) //for every column (tile)
4381 {
4382 if((((ty*width)+tx)%zc_max(LeechUpdate, 1))==0) //update status
4383 {
4384 FONT *oldfont = font;
4385 static BITMAP *tbar = create_bitmap_ex(8,240-6, 18);
4386 static bool created_tbar=false;
4387 jwin_draw_win(status, 0, 0, 240, 140, FR_WIN);
4388
4389 if(created_tbar)
4390 {
4391 blit(tbar, status, 0, 0, 3, 3, 240-6, 18);
4392 }
4393 else
4394 {
4395 font = get_zc_font(font_lfont);
4396 jwin_draw_titlebar(tbar, 0, 0, 240-6, 18, "Leech Status", false);
4397 font = oldfont;
4398 created_tbar=true;
4399 blit(tbar, status, 0, 0, 3, 3, 320-6, 18);
4400 }
4401
4402 textprintf_centre_ex(status,font,120,24,jwin_pal[jcTEXTFG],-1,"Checking %d of %d",((ty*width)+tx), (width*height));
4403 textprintf_centre_ex(status,font,120,34,jwin_pal[jcTEXTFG],-1,"%d tiles imported",currtile-start);
4404 jwin_draw_frame(status, 40, 49, 160, 70, FR_ETCHED);
4405 textprintf_centre_ex(status,font,120,46,jwin_pal[jcTEXTFG],jwin_pal[jcBOX]," Duplicates ");
4406 textprintf_centre_ex(status,font,120,56,jwin_pal[jcTEXTFG],-1,"%d/%d found/discarded",total_duplicates_found, total_duplicates_discarded);
4407 textprintf_centre_ex(status,font,120,76,jwin_pal[jcTEXTFG],-1,"%d normal %s",duplicates_found[0],((DuplicateAction[0]<2)?"found":"discarded"));
4408 textprintf_centre_ex(status,font,120,86,jwin_pal[jcTEXTFG],-1,"%d flipped (h) %s",duplicates_found[1],((DuplicateAction[1]<2)?"found":"discarded"));
4409 textprintf_centre_ex(status,font,120,96,jwin_pal[jcTEXTFG],-1,"%d flipped (v) %s",duplicates_found[2],((DuplicateAction[2]<2)?"found":"discarded"));
4410 textprintf_centre_ex(status,font,120,106,jwin_pal[jcTEXTFG],-1,"%d flipped (hv) %s",duplicates_found[3],((DuplicateAction[3]<2)?"found":"discarded"));
4411 textprintf_centre_ex(status,font,120,128,jwin_pal[jcTEXTFG],-1,"Press any key to stop.");
4412 blit(status,screen,0, 0, 40, 20, 240, 140);
4413 SCRFIX();
4414 }
4415
4416 canadd=true;
4417
4418 if(currtile>=NEWMAXTILES) //if we've maxed out on our tiles...
4419 {
4420 delete[] testtile;
4421 return true;
4422 }
4423
4424 switch(imagetype)
4425 {
4426 case ftBIN:
4427 break;
4428
4429 case ftZGP:
4430 case ftQST:
4431 case ftZQT:
4432 case ftQSU:
4433 case ftTIL:
4434 memset(testtile, 0, tilesize(tf32Bit));
4435 imported_format=grabtilebuf[tx].format;
4436
4437 switch(cdepth)
4438 {
4439 case 1: //4-bit
4440 newformat=tf4Bit;
4441
4442 switch(imported_format)
4443 {
4444 case tf4Bit:
4445 case tf8Bit:
4446 for(int32_t y=0; y<16; y++) //snag a tile
4447 {
4448 for(int32_t x=0; x<16; x+=2)
4449 {
4450 testtile[(y*8)+(x/2)]=
4451 (grabtilebuf[tx].data[y*16+x]&15)+
4452 ((grabtilebuf[tx].data[y*16+x+1]&15)<<4);
4453 }
4454 }
4455
4456 break;
4457 }
4458
4459 break;
4460
4461 case 2: //8-bit
4462 newformat=tf8Bit;
4463
4464 switch(imported_format)
4465 {
4466 case tf4Bit:
4467 unpack_tile(grabtilebuf, tx, 0, true);
4468 cst = cs&15;
4469 cst <<= CSET_SHFT;
4470
4471 for(int32_t i=0; i<256; i++)
4472 {
4473 if(!shift||unpackbuf[i]!=0)
4474 {
4475 unpackbuf[i]+=cst;
4476 }
4477 }
4478
4479 pack_tiledata(testtile, unpackbuf, tf8Bit);
4480 break;
4481
4482 case tf8Bit:
4483 memcpy(testtile,grabtilebuf[tx].data,tilesize(imported_format));
4484 break;
4485 }
4486
4487 break;
4488
4489 case 3: //original tile's bit depth
4490 newformat=imported_format;
4491 memcpy(testtile,grabtilebuf[tx].data,tilesize(imported_format));
4492 break;
4493 }
4494
4495 break;
4496
4497 case ftBMP:
4498 newformat=cdepth;
4499
4500 for(int32_t y=0; y<16; y++) //snag a tile
4501 {
4502 for(int32_t x=0; x<16; x+=2)
4503 {
4504 testtile[(y*16)+x]=getpixel(((BITMAP*)imagebuf),(tx*16)+x,(ty*16)+y);
4505 testtile[(y*16)+x+1]=getpixel(((BITMAP*)imagebuf),(tx*16)+x+1,(ty*16)+y);
4506 }
4507 }
4508
4509 break;
4510 }
4511
4512 if(DuplicateAction[0]+DuplicateAction[1]+DuplicateAction[2]+DuplicateAction[3]>0)
4513 {
4514 temp_canadd=true;
4515
4516 //check all tiles before this one
4517 for(int32_t checktile=((OnlyCheckNewTilesForDuplicates!=0)?start:0); ((temp_canadd==true)&&(checktile<currtile)); checktile++)
4518 {
4519 for(int32_t flipping=0; ((temp_canadd==true)&&(flipping<4)); ++flipping)
4520 {
4521 if(DuplicateAction[flipping]>0)
4522 {
4523 if(keypressed())
4524 {
4525 delete[] testtile;
4526 return true;
4527 }
4528
4529 duplicate=(newformat==imported_format);
4530
4531 if(duplicate)
4532 {
4533 switch(flipping)
4534 {
4535 case 0: //normal
4536 if(dest[checktile].data!=NULL)
4537 {
4538 for(int32_t y=0; ((duplicate==true)&&(y<16)); y++)
4539 {
4540 for(int32_t x=0; ((duplicate==true)&&(x<16)); x+=3-newformat)
4541 {
4542 // if ((dest[(checktile*128)+(y*8)+(x/2)])!=(testtile[(y*8)+(x/2)]))
4543 if((dest[checktile].data[(y*8*newformat)+(x/(3-newformat))])!=testtile[(y*16)+x])
4544 {
4545 duplicate=false;
4546 }
4547 }
4548 }
4549 }
4550
4551 break;
4552
4553 case 1: //horizontal
4554 if(dest[checktile].data!=NULL)
4555 {
4556 for(int32_t y=0; ((duplicate==true)&&(y<16)); y++)
4557 {
4558 for(int32_t x=0; ((duplicate==true)&&(x<16)); x+=3-newformat)
4559 {
4560 // if ((dest[(checktile*128)+(y*8)+((14-x)/2)])!=(((testtile[(y*8)+(x/2)]&15)<<4)+((testtile[(y*8)+(x/2)]>>4)&15)))
4561 if((dest[checktile].data[(y*8*newformat)+(14+(newformat-1)-x)/(3-newformat)])!=testtile[(y*16)+x])
4562 {
4563 duplicate=false;
4564 }
4565 }
4566 }
4567 }
4568
4569 break;
4570
4571 case 2: //vertical
4572 if(dest[checktile].data!=NULL)
4573 {
4574 for(int32_t y=0; ((duplicate==true)&&(y<16)); y++)
4575 {
4576 for(int32_t x=0; ((duplicate==true)&&(x<16)); x+=3-newformat)
4577 {
4578 // if ((dest[(checktile*128)+((15-y)*8)+(x/2)])!=(testtile[(y*8)+(x/2)]))
4579 if((dest[checktile].data[((15-y)*8*newformat)+(x/(3-newformat))])!=testtile[(y*16)+x])
4580 {
4581 duplicate=false;
4582 }
4583 }
4584 }
4585 }
4586
4587 break;
4588
4589 case 3: //both
4590 if(dest[checktile].data!=NULL)
4591 {
4592 for(int32_t y=0; ((duplicate==true)&&(y<16)); y++)
4593 {
4594 for(int32_t x=0; ((duplicate==true)&&(x<16)); x+=3-newformat)
4595 {
4596 // if ((dest[(checktile*128)+((15-y)*8)+((14-x)/2)])!=(((testtile[(y*8)+(x/2)]&15)<<4)+((testtile[(y*8)+(x/2)]>>4)&15)))
4597 if((dest[checktile].data[((15-y)*8*newformat)+((14+(newformat-1)-x)/(3-newformat))])!=testtile[(y*16)+x])
4598 {
4599 duplicate=false;
4600 }
4601 }
4602 }
4603 }
4604
4605 break;
4606 }
4607 }
4608
4609 if(duplicate==true)
4610 {
4611 ++duplicates_found[flipping];
4612 ++total_duplicates_found;
4613
4614 if(DuplicateAction[flipping]>1)
4615 {
4616 ++total_duplicates_discarded;
4617 temp_canadd=false;
4618 }
4619 }
4620 }
4621
4622 canadd=canadd&&temp_canadd;
4623 }
4624 }
4625 }
4626
4627 // dest[currtile].format=(cdepth==3?imported_format:cdepth);
4628 dest[currtile].format=newformat;
4629
4630 if(dest[currtile].data!=NULL)
4631 {
4632 free(dest[currtile].data);
4633 }
4634
4635 dest[currtile].data=(byte *)malloc(tilesize(dest[currtile].format));
4636
4637 if(dest[currtile].data==NULL)
4638 {
4639 Z_error_fatal("Unable to initialize tile #%d.\n", currtile);
4640 }
4641
4642 if(canadd==true)
4643 {
4644 /*
4645 for(int32_t y=0; y<16; y++)
4646 {
4647 for(int32_t x=0; x<8; x++)
4648 {
4649 dest[currtile].data[(y*8)+x]=testtile[(y*8)+x];
4650 }
4651 }
4652 */
4653 memcpy(dest[currtile].data, testtile, tilesize(dest[currtile].format));
4654 ++currtile;
4655 }
4656 }
4657 }
4658
4659 destroy_bitmap(status);
4660 delete[] testtile;
4661 return true;
4662 }
4663
4664 void grab(byte(*dest)[256],byte *def, int32_t width, int32_t height, int32_t oformat, byte *newformat)
4665 {
4666 byte defFormat=(bp==8) ? tf8Bit : tf4Bit;
4667 byte format=defFormat;
4668 int32_t stile = ((imagey*TILES_PER_ROW)+imagex)+(((sely/16)*TILES_PER_ROW)+(selx/16));
4669
4670 switch(imagetype)
4671 {
4672 case ftZGP:
4673 case ftQST:
4674 case ftZQT:
4675 case ftQSU:
4676 case ftTIL:
4677 case ftBIN:
4678 case ftBMP:
4679 for(int32_t ty=0; ty<height; ty++)
4680 {
4681 for(int32_t tx=0; tx<width; tx++)
4682 {
4683 format=defFormat;
4684 switch(imagetype)
4685 {
4686 case ftZGP:
4687 case ftQST:
4688 case ftZQT:
4689 case ftQSU:
4690 case ftTIL:
4691 format=grabtilebuf[stile+((ty*TILES_PER_ROW)+tx)].format;
4692 break;
4693 }
4694
4695 bool ever_did_unmasked = false;
4696
4697 for(int32_t y=0; y<16; y++)
4698 {
4699 for(int32_t x=0; x<16; x+=2)
4700 {
4701 bool masked = (y<8 && x<8 && grabmask&1) || (y<8 && x>7 && grabmask&2) || (y>7 && x<8 && grabmask&4) || (y>7 && x>7 && grabmask&8);
4702 if (masked)
4703 {
4704 dest[(ty*TILES_PER_ROW)+tx][(y*16)+(x)]=def[(y*16)+(x)];
4705 dest[(ty*TILES_PER_ROW)+tx][(y*16)+(x+1)]=def[(y*16)+(x+1)];
4706 }
4707 else
4708 {
4709 dest[(ty*TILES_PER_ROW)+tx][(y*16)+x]=getpixel(screen2,(tx*16)+x+selx,(ty*16)+y+sely);
4710 dest[(ty*TILES_PER_ROW)+tx][(y*16)+x+1]=getpixel(screen2,(tx*16)+x+1+selx,(ty*16)+y+sely);
4711 ever_did_unmasked = true;
4712 }
4713 if (format == tf4Bit)
4714 {
4715 dest[(ty*TILES_PER_ROW)+tx][(y*16)+x] &= 15;
4716 dest[(ty*TILES_PER_ROW)+tx][(y*16)+x+1] &= 15;
4717 }
4718 }
4719 }
4720
4721 if (ever_did_unmasked)
4722 newformat[(ty*TILES_PER_ROW)+tx] = format;
4723 }
4724 }
4725
4726 break;
4727
4728 default:
4729 for(int32_t i=0; i<200; i++)
4730 {
4731 for(int32_t j=0; j<256; j++)
4732 {
4733 dest[i][j]=0;
4734 }
4735
4736 newformat[i] = tf4Bit;
4737 }
4738
4739 break;
4740 }
4741 }
4742
4743 static void scale_imagebuf_bitmap()
4744 {
4745 imagebuf_bitmap_scale = std::clamp(imagebuf_bitmap_scale, -10, 10);
4746
4747 float scale = IMAGEBUF_SCALE;
4748 int nw = original_imagebuf_bitmap->w * scale;
4749 int nh = original_imagebuf_bitmap->h * scale;
4750 if (nw <= 0 || nh <= 0)
4751 return;
4752
4753 BITMAP* scaled_bmp = create_bitmap_ex(8, nw, nh);
4754 if (!scaled_bmp)
4755 return;
4756
4757 stretch_blit(original_imagebuf_bitmap, scaled_bmp, 0, 0, original_imagebuf_bitmap->w, original_imagebuf_bitmap->h, 0, 0, nw, nh);
4758 if (imagebuf != original_imagebuf_bitmap)
4759 destroy_bitmap((BITMAP*)imagebuf);
4760 imagebuf = scaled_bmp;
4761 }
4762
4763 //Grabber is not grabbing to tile pages beyond pg. 252 right now. -ZX 18th June, 2019
4764 void grab_tile(int32_t tile,int32_t &cs)
4765 {
4766 zq_allow_tile_draw_cache = true;
4767
4768 int window_w = 640+6+6, window_h = 480+25+6;
4769 int window_x=(zq_screen_w-window_w)/2;
4770 int window_y=(zq_screen_h-window_h)/2;
4771 popup_zqdialog_start(window_x,window_y,window_w,window_h,-1);
4772 int window_xofs = 0;
4773 int screen_xofs=6;
4774 int screen_yofs=25;
4775 int panel_yofs=0;
4776 int bwidth = 61*1.5;
4777 int bheight = 20*1.5;
4778 int button_x = 255*2;
4779 int grab_ok_button_y = 168*2 + 32;
4780 int leech_button_x = 117*2;
4781 int leech_button_y = 166*2 + 32;
4782 int grab_cancel_button_y = 192*2 + 32;
4783 int file_button_y = 216*2 + 32;
4784 int rec_button_x = 117*2;
4785 int rec_button_y = 192*2 + 32;
4786
4787 int screen_y1 = 24;
4788 int screen_y2 = screen_y1+320-1;
4789
4790 int crect_x = 184+190;
4791 int crect_y = 168*2 + 32;
4792 int crect_w = 8*2;
4793 int crect_h = 8*2;
4794
4795 int xrect_x = 640 + 12 - 21;
4796 int xrect_y = 5;
4797
4798 byte newtile[200][256];
4799 BITMAP *screen3=create_bitmap_ex(8, zq_screen_w, zq_screen_h);
4800 clear_bitmap(screen3);
4801 byte newformat[200];
4802
4803 memset(newtile, 0, 200*256);
4804 memset(newformat, 0, 200);
4805
4806 static EXT_LIST list[] =
4807 {
4808 { (char *)"All Files (*.*)", NULL },
4809 { (char *)"Bitmap Image (*.bmp)", (char *)"bmp" },
4810 { (char *)"GIF Image (*.gif)", (char *)"gif" },
4811 { (char *)"JPEG Image (*.jpg, *.jpeg)", (char *)"jpg,jpeg" },
4812 { (char *)"ZC Tile Export (*.til)", (char *)"til" },
4813 { (char *)"ZC Quest Template (*.zqt)", (char *)"zqt" },
4814 { (char *)"ZC Quest (*.qst)", (char *)"qst" },
4815 { (char *)"ZC Graphics Pack (*.zgp)", (char *)"zgp" },
4816 { (char *)"ZC Unencoded Quest (*.qsu)", (char *)"qsu" },
4817 { (char *)"NES ROM Image (*.nes)", (char *)"nes" },
4818 { (char *)"SNES ROM Image (*.smc)", (char *)"smc" },
4819 { (char *)"Gameboy ROM Image (*.gb)", (char *)"gb" },
4820 { (char *)"Gameboy Advance ROM Image (*.gba)", (char *)"gba" },
4821 { NULL, NULL }
4822 };
4823
4824
4825 memset(cset_reduce_table, 0, 256);
4826 memset(col_diff,0,3*128);
4827 bool bdown=false;
4828 int done=0;
4829 int pal=0;
4830 int f=0;
4831 int black=vc(0),white=vc(15);
4832 int selwidth=1, selheight=1;
4833 int selx2=0, sely2=0;
4834 bool xreversed=false, yreversed=false;
4835 bool doleech=false, dofile=false, dopal=false;
4836
4837 int jwin_pal2[jcMAX];
4838 memcpy(jwin_pal2, jwin_pal, sizeof(int)*jcMAX);
4839
4840
4841 if(imagebuf==NULL)
4842 load_imagebuf();
4843
4844 calc_cset_reduce_table(imagepal, cs);
4845 calc_cset_reduce_table_8bit(imagepal);
4846 draw_grab_window();
4847 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
4848 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
4849
4850 while(gui_mouse_b())
4851 {
4852 /* do nothing */
4853 rest(1);
4854 }
4855
4856 do
4857 {
4858 HANDLE_CLOSE_ZQDLG();
4859 if(exiting_program) break;
4860 rest(4);
4861 bool redraw=false;
4862
4863 if(keypressed())
4864 {
4865 redraw=true;
4866
4867 switch(readkey()>>8)
4868 {
4869 case KEY_F:
4870 dofile=true;
4871 break;
4872
4873 case KEY_L:
4874 doleech=true;
4875 break;
4876
4877 case KEY_P:
4878 if(imagetype==ftBMP)
4879 {
4880 dopal=true;
4881 recolor=rcNone;
4882 calc_cset_reduce_table(imagepal, cs);
4883 }
4884
4885 break;
4886
4887 case KEY_ESC:
4888 done=1;
4889 break;
4890
4891 case KEY_ENTER_PAD:
4892 case KEY_ENTER:
4893 done=2;
4894 break;
4895
4896 case KEY_DOWN:
4897 if(CHECK_CTRL_CMD) sely=zc_min(sely+1,144);
4898 else ++imagey;
4899
4900 break;
4901
4902 case KEY_UP:
4903 if(CHECK_CTRL_CMD) sely=zc_max(sely-1,0);
4904 else --imagey;
4905
4906 break;
4907
4908 case KEY_RIGHT:
4909 if(CHECK_CTRL_CMD) selx=zc_min(selx+1,304);
4910 else ++imagex;
4911
4912 break;
4913
4914 case KEY_LEFT:
4915 if(CHECK_CTRL_CMD) selx=zc_max(selx-1,0);
4916 else --imagex;
4917
4918 break;
4919
4920 case KEY_PGDN:
4921 imagey+=10;
4922 break;
4923
4924 case KEY_PGUP:
4925 imagey-=10;
4926 break;
4927
4928 case KEY_HOME:
4929 imagex=imagey=0;
4930 break;
4931
4932 case KEY_EQUALS:
4933 case KEY_PLUS_PAD:
4934 cs = (cs<13) ? cs+1:0;
4935 if(recolor==rc4Bit)
4936 calc_cset_reduce_table(imagepal, cs);
4937 break;
4938
4939 case KEY_MINUS:
4940 case KEY_MINUS_PAD:
4941 cs = (cs>0) ? cs-1:13;
4942 if(recolor==rc4Bit)
4943 calc_cset_reduce_table(imagepal, cs);
4944 break;
4945
4946 case KEY_S:
4947 if(grabmode==1) grabmode=8;
4948 else if(grabmode==8) grabmode=16;
4949 else grabmode=1;
4950
4951 break;
4952
4953 case KEY_COMMA:
4954 if (imagetype == ftBMP)
4955 {
4956 imagebuf_bitmap_scale--;
4957 if (imagebuf_bitmap_scale == 0)
4958 imagebuf_bitmap_scale = -2;
4959 scale_imagebuf_bitmap();
4960 }
4961 break;
4962 case KEY_STOP:
4963 if (imagetype == ftBMP)
4964 {
4965 imagebuf_bitmap_scale++;
4966 if (imagebuf_bitmap_scale == -1)
4967 imagebuf_bitmap_scale = 1;
4968 scale_imagebuf_bitmap();
4969 }
4970 break;
4971
4972 case KEY_1:
4973 if(recolor==rc8Bit)
4974 recolor=rcNone;
4975 //imagex=(imagex*bp)>>3;
4976 bp=1;
4977 //imagex<<=3;
4978 nesmode=false;
4979 break;
4980
4981 case KEY_2:
4982 if(recolor==rc8Bit)
4983 recolor=rcNone;
4984 //imagex=(imagex*bp)>>3;
4985 bp=2;
4986 //imagex<<=2;
4987 nesmode=false;
4988 break;
4989
4990 case KEY_N:
4991 if(recolor==rc8Bit)
4992 recolor=rcNone;
4993 //imagex=(imagex*bp)>>3;
4994 bp=2;
4995 //imagex<<=2;
4996 nesmode=true;
4997 break;
4998
4999 case KEY_4:
5000 if(recolor==rc8Bit)
5001 recolor=rcNone;
5002 //imagex=(imagex*bp)>>3;
5003 bp=4;
5004 //imagex<<=1;
5005 nesmode=false;
5006 break;
5007
5008 case KEY_8:
5009 //imagex=(imagex*bp)>>3;
5010 bp=8;
5011 break;
5012
5013 case KEY_B:
5014 if(bp==2&&!nesmode)
5015 {
5016 nesmode=true;
5017 }
5018 else
5019 {
5020 nesmode=false;
5021 bp<<=1;
5022
5023 if(bp==16)
5024 {
5025 bp=1;
5026 //imagex<<=3;
5027 }
5028 else
5029 {
5030 //imagex>>=1;
5031 }
5032 }
5033
5034 break;
5035
5036 case KEY_M:
5037 romtilemode=(romtilemode+1)%4;
5038 break;
5039
5040 case KEY_Z:
5041 if(romofs>0) --romofs;
5042
5043 break;
5044
5045 case KEY_X:
5046 ++romofs;
5047 break;
5048
5049 case KEY_R:
5050 if(pal)
5051 {
5052 dopal=true;
5053 }
5054
5055 if(recolor!=rcNone)
5056 recolor=rcNone;
5057 else if(key[KEY_LSHIFT] || key[KEY_RSHIFT])
5058 {
5059 bp=8;
5060 recolor=rc8Bit;
5061 calc_cset_reduce_table_8bit(imagepal);
5062 }
5063 else
5064 {
5065 if(bp==8)
5066 bp=4;
5067 recolor=rc4Bit;
5068 calc_cset_reduce_table(imagepal, cs);
5069 }
5070 break;
5071
5072 default:
5073 redraw=false;
5074 }
5075
5076 clear_keybuf();
5077
5078 if(imagex<0) imagex=0;
5079
5080 if(imagey<0) imagey=0;
5081
5082 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
5083 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
5084 }
5085
5086 //boogie!
5087 if(gui_mouse_b()==1 && !bdown)
5088 {
5089 int x=gui_mouse_x();
5090 int y=gui_mouse_y();
5091 if(isinRect(x,y,xrect_x, xrect_y, xrect_x + 15, xrect_y + 13))
5092 if(do_x_button(screen, xrect_x, xrect_y))
5093 done=1;
5094
5095 if(!bdown)
5096 {
5097 bool regrab=false;
5098 bdown=true;
5099 FONT* oldfont = font;
5100 font = get_zc_font(font_lfont_l);
5101
5102 if(y>=screen_y1 && y<=screen_y2)
5103 {
5104 do
5105 {
5106 HANDLE_CLOSE_ZQDLG();
5107 if(exiting_program) break;
5108 int x = (gui_mouse_x()-screen_xofs) / 2;
5109 int y = (gui_mouse_y()-screen_yofs) / 2;
5110
5111 int ox=selx,oy=sely,ow=selwidth,oh=selheight;
5112
5113 if(!(key[KEY_LSHIFT] || key[KEY_RSHIFT]))
5114 {
5115 selx=vbound((x/grabmode)*grabmode,0,304);
5116 sely=vbound((y/grabmode)*grabmode,0,144);
5117 selx2=selx;
5118 sely2=sely;
5119 selwidth=1;
5120 selheight=1;
5121 xreversed=false;
5122 yreversed=false;
5123 }
5124 else
5125 {
5126 if(xreversed)
5127 {
5128 zc_swap(selx, selx2);
5129 xreversed=false;
5130 }
5131
5132 if(yreversed)
5133 {
5134 zc_swap(sely, sely2);
5135 yreversed=false;
5136 }
5137
5138 selx2=vbound((x/grabmode)*grabmode,0,304);
5139 sely2=vbound((y/grabmode)*grabmode,0,144);
5140 selwidth=1+(abs(selx2-selx))/16;
5141 selheight=1+(abs(sely2-sely))/16;
5142
5143 if(selx2<selx)
5144 {
5145 zc_swap(selx, selx2);
5146 xreversed=true;
5147 }
5148
5149 if(sely2<sely)
5150 {
5151 zc_swap(sely, sely2);
5152 yreversed=true;
5153 }
5154 }
5155
5156 bool changed = (ox!=selx || oy!=sely || ow!=selwidth || oh!=selheight);
5157 bool redraw = changed || !(f%8);
5158
5159 if(redraw)
5160 {
5161 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
5162 if(changed)
5163 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
5164 if(f&8)
5165 {
5166 static const int w = 32;
5167 rect(screen,(selx*2)+screen_xofs,(sely*2)+screen_yofs,(selx*2)+screen_xofs+((selwidth-1)*w)+(w-1),(sely*2)+screen_yofs+((selheight-1)*w)+(w-1),white);
5168 }
5169 }
5170 else custom_vsync();
5171
5172 ++f;
5173 }
5174 while(gui_mouse_b());
5175 }
5176 else if(isinRect(x,y,button_x,grab_ok_button_y,button_x+bwidth,grab_ok_button_y+bheight))
5177 {
5178 if(do_text_button(button_x,grab_ok_button_y,bwidth,bheight,"OK"))
5179 done=2;
5180 }
5181 else if(isinRect(x,y,leech_button_x,leech_button_y,leech_button_x+bwidth,leech_button_y+bheight))
5182 {
5183 if(do_text_button(leech_button_x,leech_button_y,bwidth,bheight,"Leech"))
5184 {
5185 doleech=true;
5186 }
5187 }
5188 else if(isinRect(x,y,button_x,grab_cancel_button_y,button_x+bwidth,grab_cancel_button_y+bheight))
5189 {
5190 if(do_text_button(button_x,grab_cancel_button_y,bwidth,bheight,"Cancel"))
5191 done=1;
5192 }
5193 else if(isinRect(x,y,button_x,file_button_y,button_x+bwidth,file_button_y+bheight))
5194 {
5195 if(do_text_button(button_x,file_button_y,bwidth,bheight,"File"))
5196 {
5197 dofile=true;
5198 }
5199 }
5200 else if(imagetype == ftBMP && isinRect(x,y,rec_button_x, rec_button_y, rec_button_x+bwidth, rec_button_y+bheight))
5201 {
5202 if(do_text_button(rec_button_x,rec_button_y,bwidth,bheight,"Recolor"))
5203 {
5204 if(pal)
5205 {
5206 dopal = true;
5207 }
5208
5209 if(recolor!=rcNone)
5210 recolor=rcNone;
5211 else if(key[KEY_LSHIFT] || key[KEY_RSHIFT])
5212 {
5213 bp=8;
5214 recolor=rc8Bit;
5215 calc_cset_reduce_table_8bit(imagepal);
5216 }
5217 else
5218 {
5219 if(bp==8)
5220 bp=4;
5221 recolor=rc4Bit;
5222 calc_cset_reduce_table(imagepal, cs);
5223 }
5224 redraw=true;
5225 }
5226 }
5227 else if(isinRect(x,y+panel_yofs,crect_x,crect_y,crect_x+(16),crect_y+crect_h-1))
5228 {
5229 regrab=true;
5230 grabmask^=1;
5231 }
5232 else if(isinRect(x,y+panel_yofs,crect_x+crect_w,crect_y,crect_x+(32)-1,crect_y+crect_h-1))
5233 {
5234 regrab=true;
5235 grabmask^=2;
5236 }
5237 else if(isinRect(x,y+panel_yofs,crect_x,crect_y+crect_h,crect_x+(16)-1,crect_y+crect_h+crect_h-1))
5238 {
5239 regrab=true;
5240 grabmask^=4;
5241 }
5242 else if(isinRect(x,y+panel_yofs,crect_x+crect_w,crect_y+crect_h,crect_x+(32)-1,crect_y+crect_h+crect_h-1))
5243 {
5244 regrab=true;
5245 grabmask^=8;
5246 }
5247
5248 if(regrab)
5249 {
5250 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
5251 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
5252 redraw=true;
5253 }
5254
5255 font = oldfont;
5256 }
5257 }
5258
5259 if(gui_mouse_b()==0)
5260 bdown=false;
5261
5262 if(dofile)
5263 {
5264 if (prompt_for_existing_file_compat("Load File", "", list, imagepath, true))
5265 {
5266 zc_set_palette(RAMpal);
5267 pal=0;
5268 white=vc(15);
5269 black=vc(0);
5270 strcpy(imagepath,temppath);
5271 load_imagebuf();
5272 imagex=imagey=0;
5273 calc_cset_reduce_table(imagepal, cs);
5274 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
5275 grab(newtile,newtilebuf[tile].data, selwidth, selheight, newtilebuf[tile].format, newformat);
5276 }
5277
5278 while(key[KEY_ESC])
5279 {
5280 poll_keyboard();
5281 /* do nothing */
5282 rest(1);
5283 }
5284
5285 clear_keybuf();
5286 dofile=false;
5287 redraw=true;
5288 }
5289
5290 if(doleech)
5291 {
5292 if(leech_tiles(newtilebuf,tile,cs))
5293 {
5294 done=1;
5295 }
5296 else
5297 {
5298 while(key[KEY_ESC])
5299 {
5300 poll_keyboard();
5301 /* do nothing */
5302 rest(1);
5303 }
5304
5305 clear_keybuf();
5306 redraw=true;
5307 }
5308
5309 doleech=false;
5310 }
5311
5312 if(dopal)
5313 {
5314 pal^=1;
5315
5316 if(pal)
5317 {
5318 get_bw(imagepal,black,white);
5319
5320 jwin_pal[jcBOX] =imagepal_table.data[0][jwin_pal[jcBOX]];
5321 jwin_pal[jcLIGHT] =imagepal_table.data[0][jwin_pal[jcLIGHT]];
5322 jwin_pal[jcMEDLT] =imagepal_table.data[0][jwin_pal[jcMEDLT]];
5323 jwin_pal[jcMEDDARK]=imagepal_table.data[0][jwin_pal[jcMEDDARK]];
5324 jwin_pal[jcDARK] =imagepal_table.data[0][jwin_pal[jcDARK]];
5325 jwin_pal[jcBOXFG] =imagepal_table.data[0][jwin_pal[jcBOXFG]];
5326 jwin_pal[jcTITLEL] =imagepal_table.data[0][jwin_pal[jcTITLEL]];
5327 jwin_pal[jcTITLER] =imagepal_table.data[0][jwin_pal[jcTITLER]];
5328 jwin_pal[jcTITLEFG]=imagepal_table.data[0][jwin_pal[jcTITLEFG]];
5329 jwin_pal[jcTEXTBG] =imagepal_table.data[0][jwin_pal[jcTEXTBG]];
5330 jwin_pal[jcTEXTFG] =imagepal_table.data[0][jwin_pal[jcTEXTFG]];
5331 jwin_pal[jcSELBG] =imagepal_table.data[0][jwin_pal[jcSELBG]];
5332 jwin_pal[jcSELFG] =imagepal_table.data[0][jwin_pal[jcSELFG]];
5333 gui_bg_color=jwin_pal[jcBOX];
5334 gui_fg_color=jwin_pal[jcBOXFG];
5335 jwin_set_colors(jwin_pal);
5336 }
5337 else
5338 {
5339 white=vc(15);
5340 black=vc(0);
5341
5342 memcpy(jwin_pal, jwin_pal2, sizeof(int)*jcMAX);
5343 gui_bg_color=jwin_pal[jcBOX];
5344 gui_fg_color=jwin_pal[jcBOXFG];
5345 jwin_set_colors(jwin_pal);
5346 }
5347
5348 zc_set_palette_range(pal?imagepal:RAMpal,0,255,false);
5349
5350 dopal=false;
5351 redraw=true;
5352 }
5353
5354 if(redraw)
5355 {
5356 draw_grab_scr(tile,cs,newtile[0],black,white, selwidth, selheight, newformat);
5357 }
5358 else
5359 {
5360 custom_vsync();
5361 }
5362
5363 if((f%8)==0)
5364 {
5365 stretch_blit(screen2,screen3,0, 0, zq_screen_w, zq_screen_h, 0, 0, zq_screen_w*2, zq_screen_h*2);
5366
5367 int selxl = selx* 2;
5368 int selyl = sely* 2;
5369 int w = 32;
5370
5371 if(f&8)
5372 rect(screen3,selxl,selyl,selxl+((selwidth-1)*w)+(w-1),selyl+((selheight-1)*w)+(w-1),white);
5373
5374 blit(screen3,screen,selxl,selyl,selxl+screen_xofs,selyl+screen_yofs,selwidth*w,selheight*w);
5375 }
5376
5377 // SCRFIX();
5378 ++f;
5379
5380 }
5381 while(!done);
5382
5383 memcpy(jwin_pal, jwin_pal2, sizeof(int)*jcMAX);
5384 gui_bg_color=jwin_pal[jcBOX];
5385 gui_fg_color=jwin_pal[jcBOXFG];
5386 jwin_set_colors(jwin_pal);
5387
5388
5389 if(done==2)
5390 {
5391 go_tiles();
5392 saved=false;
5393
5394 for(int y=0; y<selheight; y++)
5395 {
5396 for(int x=0; x<selwidth; x++)
5397 {
5398 int temptile=tile+((TILES_PER_ROW*y)+x);
5399 int format=(bp==8) ? tf8Bit : tf4Bit;
5400
5401 if(newtilebuf[temptile].data!=NULL)
5402 free(newtilebuf[temptile].data);
5403
5404 newtilebuf[temptile].format=format;
5405 newtilebuf[temptile].data=(byte *)malloc(tilesize(format));
5406
5407 if(newtilebuf[temptile].data==NULL)
5408 {
5409 Z_error_fatal("Unable to initialize tile #%d.\n", temptile);
5410 break;
5411 }
5412
5413 for(int i=0; i<256; i++)
5414 {
5415 // newtilebuf[temptile].data[i] = cset_reduce_table[newtile[(TILES_PER_ROW*y)+x][i]];
5416 newtilebuf[temptile].data[i] = newtile[(TILES_PER_ROW*y)+x][i];
5417 }
5418
5419 // unpackbuf[i]=(cset_reduce_table[unpackbuf[i]]);
5420 }
5421 }
5422 }
5423
5424 destroy_bitmap(screen3);
5425
5426 if(pal)
5427 zc_set_palette(RAMpal);
5428
5429 recolor=rcNone;
5430 calc_cset_reduce_table(imagepal, cs);
5431 register_blank_tiles();
5432 popup_zqdialog_end();
5433
5434 zq_allow_tile_draw_cache = false;
5435 }
5436
5437 int32_t show_only_unused_tiles=4; //1 bit: hide used, 2 bit: hide unused, 4 bit: hide blank
5438 bool tile_is_used(int32_t tile)
5439 {
5440 return used_tile_table[tile];
5441 }
5442 void draw_tiles(int32_t first,int32_t cs, int32_t f)
5443 {
5444 draw_tiles(screen2, first, cs, f, true);
5445 }
5446 void draw_tiles(BITMAP* dest,int32_t first,int32_t cs, int32_t f, bool large, bool true_empty)
5447 {
5448 clear_bitmap(dest);
5449 BITMAP *buf = create_bitmap_ex(8,16,16);
5450
5451 int32_t w = 16;
5452 int32_t h = 16;
5453
5454 if(large)
5455 {
5456 w *=2;
5457 h *=2;
5458 }
5459
5460 for(int32_t i=0; i<TILES_PER_PAGE; i++) // 13 rows, leaving 32 pixels from y=208 to y=239
5461 {
5462 int32_t x = (i%TILES_PER_ROW)<<4;
5463 int32_t y = (i/TILES_PER_ROW)<<4;
5464 int32_t l = 16;
5465
5466 if(large)
5467 {
5468 x*=2;
5469 y*=2;
5470 l*=2;
5471 }
5472
5473 l-=2;
5474
5475 if((HIDE_USED && tile_is_used(first+i) && !blank_tile_table[first+i]) // 1 bit: hide used
5476 || (HIDE_UNUSED && !tile_is_used(first+i) && !blank_tile_table[first+i]) // 2 bit: hide unused
5477 || (HIDE_BLANK && blank_tile_table[first+i])) // 4 bit: hide blank
5478 {
5479 if(!true_empty) //Use pure color 0; no effects
5480 {
5481 if (InvalidBG == 2)
5482 {
5483 draw_checkerboard(dest, x, y, w);
5484 }
5485 else if(InvalidBG == 1)
5486 {
5487 for(int32_t dy=0; dy<=l+1; dy++)
5488 {
5489 for(int32_t dx=0; dx<=l+1; dx++)
5490 {
5491 dest->line[dy+(y)][dx+(x)]=vc((((zc_oldrand()%100)/50)?0:8)+(((zc_oldrand()%100)/50)?0:7));
5492 }
5493 }
5494 }
5495 else
5496 {
5497 for(int32_t dy=0; dy<=l+1; dy++)
5498 {
5499 for(int32_t dx=0; dx<=l+1; dx++)
5500 {
5501 dest->line[dy+(y)][dx+(x)]=vc(0);
5502 }
5503 }
5504 rect(dest, (x)+1,(y)+1, (x)+l, (y)+l, vc(15));
5505 line(dest, (x)+1,(y)+1, (x)+l, (y)+l, vc(15));
5506 line(dest, (x)+1,(y)+l, (x)+l, (y)+1, vc(15));
5507 }
5508 }
5509 }
5510 else
5511 {
5512 puttile16(buf,first+i,0,0,cs,0);
5513 stretch_blit(buf,dest,0,0,16,16,x,y,w,h);
5514 }
5515
5516 if((f%32)<=16 && large && !HIDE_8BIT_MARKER && newtilebuf[first+i].format==tf8Bit)
5517 {
5518 textprintf_ex(dest,get_zc_font(font_z3smallfont),(x)+l-3,(y)+l-3,vc(int32_t((f%32)/6)+10),-1,"8");
5519 }
5520 }
5521
5522 destroy_bitmap(buf);
5523 }
5524
5525 void tile_info_0(int32_t tile,int32_t tile2,int32_t cs,int32_t copy,int32_t copycnt,int32_t page,bool rect_sel)
5526 {
5527 int32_t yofs=3;
5528 BITMAP *buf = create_bitmap_ex(8,16,16);
5529 int32_t mul = 2;
5530 FONT *tfont = get_zc_font(font_pfont);
5531
5532 rectfill(screen2,0,210*2,(320*2)-1,(240*2),jwin_pal[jcBOX]);
5533 hline(screen2, 0, (210*2)-2, (320*2)-1, jwin_pal[jcMEDLT]);
5534 hline(screen2, 0, (210*2)-1, (320*2)-1, jwin_pal[jcLIGHT]);
5535 tfont = get_zc_font(font_lfont_l);
5536
5537 // Copied tile and numbers
5538 jwin_draw_frame(screen2,(34*mul)-2,((216*mul)+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5539 int32_t coldiff=TILECOL(copy)-TILECOL(copy+copycnt-1);
5540 if(copy>=0)
5541 {
5542 puttile16(buf,rect_sel&&coldiff>0?copy-coldiff:copy,0,0,cs,0);
5543 stretch_blit(buf,screen2,0,0,16,16,34*mul,216*mul+yofs,16*mul,16*mul);
5544
5545 if(copycnt>1)
5546 {
5547 textprintf_right_ex(screen2,tfont,28*mul,(216*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d-",copy);
5548 textprintf_right_ex(screen2,tfont,24*mul,(224*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",copy+copycnt-1);
5549 }
5550 else
5551 {
5552 textprintf_right_ex(screen2,tfont,24*mul,(220*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",copy);
5553 }
5554 }
5555 else // No tiles copied
5556 {
5557 if (InvalidBG == 2)
5558 {
5559 draw_checkerboard(screen2, 34 * mul, 216 * mul + yofs, 16 * mul);
5560 }
5561 else if(InvalidBG == 1)
5562 {
5563 for(int32_t dy=0; dy<16*mul; dy++)
5564 {
5565 for(int32_t dx=0; dx<16*mul; dx++)
5566 {
5567 screen2->line[(216*mul+yofs+dy)][36*mul+dx]=vc((((zc_oldrand()%100)/50)?0:8)+(((zc_oldrand()%100)/50)?0:7));
5568 }
5569 }
5570 }
5571 else
5572 {
5573 rectfill(screen2, 34*mul, (216*mul)+yofs, (34+15)*mul, ((216+15)*mul)+yofs, vc(0));
5574 rect(screen2, 34*mul, (216*mul)+yofs, (34+15)*mul, ((216+15)*mul)+yofs, vc(15));
5575 line(screen2, 34*mul, (216*mul)+yofs, (34+15)*mul, ((216+15)*mul)+yofs, vc(15));
5576 line(screen2, 34*mul, ((216+15)*mul)+yofs, (34+15)*mul, (216*mul)+yofs, vc(15));
5577 }
5578 }
5579
5580
5581 // Current tile
5582 jwin_draw_frame(screen2,(104*mul)-2,(216*mul+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5583 puttile16(buf,tile,0,0,cs,0);
5584 stretch_blit(buf,screen2,0,0,16,16,104*mul,216*mul+yofs,16*mul,16*mul);
5585
5586 // Current selection mode
5587 jwin_draw_frame(screen2,(127*mul)-2,(216*mul+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5588 stretch_blit(select_bmp[rect_sel?1:0],screen2,0,0,16,16,127*mul,216*mul+yofs,16*mul,16*mul);
5589
5590 if(tile>tile2)
5591 {
5592 zc_swap(tile,tile2);
5593 }
5594
5595 char tbuf[8];
5596 tbuf[0]=0;
5597
5598 if(tile2!=tile)
5599 {
5600 sprintf(tbuf,"-%d",tile2);
5601 }
5602
5603 // Current tile and CSet text
5604 textprintf_ex(screen2,tfont,55*mul,216*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"cs: %d",cs);
5605 textprintf_right_ex(screen2,tfont,99*mul,216*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"tile:");
5606 textprintf_right_ex(screen2,tfont,99*mul,224*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d%s",tile,tbuf);
5607
5608 FONT *tf = font;
5609 font = tfont;
5610
5611 draw_text_button(screen2,150*mul,213*mul+yofs,28*mul,21*mul,"&Grab",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5612 draw_text_button(screen2,(150+28)*mul,213*mul+yofs,28*mul,21*mul,"&Edit",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5613 draw_text_button(screen2,(150+28*2)*mul,213*mul+yofs,28*mul,21*mul,"Export",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5614 draw_text_button(screen2,(150+28*3)*mul,213*mul+yofs,28*mul,21*mul,"Recolor",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5615 draw_text_button(screen2,(150+28*4)*mul,213*mul+yofs,28*mul,21*mul,"Done",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
5616
5617 jwin_draw_icon(screen2,(305*mul+4),220*mul-6+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_UP,6,true);
5618 textprintf_ex(screen2,tfont,293*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"p:");
5619 textprintf_centre_ex(screen2,tfont,(305*mul+4),220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",page);
5620 jwin_draw_icon(screen2,(305*mul+4),228*mul+3+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_DOWN,6,true);
5621
5622 font = tf;
5623
5624 int32_t w = 640;
5625 int32_t h = 480;
5626 int32_t window_xofs=(zq_screen_w-w-12)>>1;
5627 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
5628 int32_t screen_xofs=window_xofs+6;
5629 int32_t screen_yofs=window_yofs+25;
5630
5631 custom_vsync();
5632 blit(screen2,screen,0,0,screen_xofs,screen_yofs,w,h);
5633 SCRFIX();
5634 destroy_bitmap(buf);
5635 }
5636
5637 void tile_info_1(int32_t oldtile,int32_t oldflip,int32_t oldcs,int32_t tile,int32_t flip,int32_t cs,int32_t copy,int32_t page, bool always_use_flip)
5638 {
5639 int32_t yofs=3;
5640 BITMAP *buf = create_bitmap_ex(8,16,16);
5641 int32_t mul = 2;
5642 FONT *tfont = get_zc_font(font_pfont);
5643
5644 rectfill(screen2,0,210*2,(320*2)-1,(240*2),jwin_pal[jcBOX]);
5645 hline(screen2, 0, (210*2)-2, (320*2)-1, jwin_pal[jcMEDLT]);
5646 hline(screen2, 0, (210*2)-1, (320*2)-1, jwin_pal[jcLIGHT]);
5647 tfont = get_zc_font(font_lfont_l);
5648
5649 jwin_draw_frame(screen2,(124*mul)-2,((216*mul)+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5650
5651 if(copy>=0)
5652 {
5653 puttile16(buf,copy,0,0,cs,flip);
5654 stretch_blit(buf,screen2,0,0,16,16,124*mul,216*mul+yofs,16*mul,16*mul);
5655 }
5656 else
5657 {
5658 if (InvalidBG == 2)
5659 {
5660 draw_checkerboard(screen2, 124 * mul, 216 * mul + yofs, 16 * mul);
5661 }
5662 else if(InvalidBG == 1)
5663 {
5664 for(int32_t dy=0; dy<16*mul; dy++)
5665 {
5666 for(int32_t dx=0; dx<16*mul; dx++)
5667 {
5668 screen2->line[216*mul+yofs+dy][124*mul+dx]=vc((((zc_oldrand()%100)/50)?0:8)+(((zc_oldrand()%100)/50)?0:7));
5669 }
5670 }
5671 }
5672 else
5673 {
5674 rectfill(screen2, 124*mul, (216*mul)+yofs, (124+15)*mul, ((216+15)*mul)+yofs, vc(0));
5675 rect(screen2, 124*mul, (216*mul)+yofs, (124+15)*mul, ((216+15)*mul)+yofs, vc(15));
5676 line(screen2, 124*mul, (216*mul)+yofs, (124+15)*mul, ((216+15)*mul)+yofs, vc(15));
5677 line(screen2, 124*mul, ((216+15)*mul)+yofs, (124+15)*mul, (216*mul)+yofs, vc(15));
5678 }
5679 }
5680
5681 jwin_draw_frame(screen2,(8*mul)-2,(216*mul+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5682 puttile16(buf,oldtile,0,0, oldcs, oldflip);
5683 stretch_blit(buf,screen2,0,0,16,16,8*mul,216*mul+yofs,16*mul,16*mul);
5684
5685 textprintf_right_ex(screen2,tfont,56*mul,212*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Old Tile:");
5686 textprintf_ex(screen2,tfont,60*mul,212*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",oldtile);
5687
5688 textprintf_right_ex(screen2,tfont,56*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"CSet:");
5689 textprintf_ex(screen2,tfont,60*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",oldcs);
5690
5691 if(oldflip > 0 || always_use_flip) // Suppress Flip for this usage
5692 {
5693 textprintf_right_ex(screen2,tfont,56*mul,228*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Flip:");
5694 textprintf_ex(screen2,tfont,60*mul,228*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",oldflip);
5695 }
5696
5697 jwin_draw_frame(screen2,(148*mul)-2,(216*mul+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
5698 puttile16(buf,tile,0,0, cs,
5699 (oldflip>0 || always_use_flip)?flip:0); // Suppress Flip for this usage
5700 stretch_blit(buf,screen2,0,0,16,16,148*mul,216*mul+yofs,16*mul,16*mul);
5701
5702 textprintf_right_ex(screen2,tfont,201*mul,212*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"New Tile:");
5703 textprintf_ex(screen2,tfont,205*mul,212*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",tile);
5704 textprintf_right_ex(screen2,tfont,201*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"CSet:");
5705 textprintf_ex(screen2,tfont,205*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",cs);
5706
5707 if(oldflip > 0 || always_use_flip) // Suppress Flip for this usage
5708 {
5709 textprintf_right_ex(screen2,tfont,201*mul,228*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Flip:");
5710 textprintf_ex(screen2,tfont,205*mul,228*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",flip);
5711 }
5712
5713 jwin_draw_icon(screen2,(305*mul+4),220*mul-6+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_UP,6,true);
5714 textprintf_ex(screen2,tfont,293*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"p:");
5715 textprintf_centre_ex(screen2,tfont,309*mul,220*mul+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",page);
5716 jwin_draw_icon(screen2,(305*mul+4),228*mul+3+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_DOWN,6,true);
5717
5718
5719 int32_t w = 640;
5720 int32_t h = 480;
5721 int32_t window_xofs=(zq_screen_w-w-12)>>1;
5722 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
5723 int32_t screen_xofs=window_xofs+6;
5724 int32_t screen_yofs=window_yofs+25;
5725
5726 custom_vsync();
5727 blit(screen2,screen,0,0,screen_xofs,screen_yofs,w,h);
5728 SCRFIX();
5729 destroy_bitmap(buf);
5730 }
5731 /*
5732 void reset_tile(tiledata *buf, int32_t t, int32_t format=1)
5733 {
5734 buf[t].format=format;
5735 if (buf[t].data!=NULL)
5736 {
5737 free(buf[t].data);
5738 }
5739 buf[t].data=(byte *)malloc(tilesize(buf[t].format));
5740 if (buf[t].data==NULL)
5741 {
5742 Z_error_fatal("Unable to initialize tile #%d.\n", t);
5743 }
5744 for(int32_t i=0; i<tilesize(buf[t].format); i++)
5745 {
5746 buf[t].data[i]=0;
5747 }
5748 }
5749 */
5750
5751 int32_t hide_used()
5752 {
5753 show_only_unused_tiles ^= 1;
5754 return D_O_K;
5755 }
5756 int32_t hide_unused()
5757 {
5758 show_only_unused_tiles ^= 2;
5759 return D_O_K;
5760 }
5761 int32_t hide_blank()
5762 {
5763 show_only_unused_tiles ^= 4;
5764 return D_O_K;
5765 }
5766 int32_t hide_8bit_marker()
5767 {
5768 show_only_unused_tiles ^= 8;
5769 return D_O_K;
5770 }
5771
5772 enum
5773 {
5774 MENUID_SELTILE_VIEW_HIDE_USED,
5775 MENUID_SELTILE_VIEW_HIDE_UNUSED,
5776 MENUID_SELTILE_VIEW_HIDE_BLANK,
5777 MENUID_SELTILE_VIEW_HIDE_8BIT,
5778 };
5779
1/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
9 static NewMenu select_tile_view_menu
5780 45 {
5781
2/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
9 { "Hide Used", hide_used, MENUID_SELTILE_VIEW_HIDE_USED },
5782
2/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
9 { "Hide Unused", hide_unused, MENUID_SELTILE_VIEW_HIDE_UNUSED },
5783
2/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
9 { "Hide Blank", hide_blank, MENUID_SELTILE_VIEW_HIDE_BLANK },
5784
2/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
9 { "Hide 8-bit marker", hide_8bit_marker, MENUID_SELTILE_VIEW_HIDE_8BIT },
5785 };
5786
5787 9 static std::function<void(int)> select_tile_color_depth_cb;
5788
5789 static void set_tile_color_depth_4()
5790 {
5791 select_tile_color_depth_cb(tf4Bit);
5792 }
5793 static void set_tile_color_depth_8()
5794 {
5795 select_tile_color_depth_cb(tf8Bit);
5796 }
5797 enum
5798 {
5799 MENUID_SELTILE_COLOR_DEPTH_4_BIT,
5800 MENUID_SELTILE_COLOR_DEPTH_8_BIT,
5801 };
5802
1/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
9 static NewMenu select_tile_color_depth_menu
5803 27 {
5804
2/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
9 { "4-bit", set_tile_color_depth_4, MENUID_SELTILE_COLOR_DEPTH_4_BIT },
5805
2/4
✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
9 { "8-bit", set_tile_color_depth_8, MENUID_SELTILE_COLOR_DEPTH_8_BIT },
5806 };
5807
5808 //returns the row the tile is in on its page
5809 int32_t tile_page_row(int32_t tile)
5810 {
5811 return TILEROW(tile)-(TILEPAGE(tile)*TILE_ROWS_PER_PAGE);
5812 }
5813
5814 enum {ti_none, ti_encompass, ti_broken};
5815
5816 //striped check and striped selection
5817 int32_t move_intersection_ss(newcombo &cmb, int32_t selection_first, int32_t selection_last, int32_t offset = 0)
5818 {
5819 int32_t cmb_first = cmb.o_tile;
5820 int32_t cmb_last = cmb.o_tile;
5821 do
5822 {
5823 cmb_last = cmb.tile;
5824 animate(cmb, true);
5825 }
5826 while(cmb.tile != cmb.o_tile);
5827 reset_combo_animation(cmb);
5828 cmb_first += offset;
5829 cmb_last += offset;
5830
5831 if(cmb_first > selection_last || cmb_last < selection_first)
5832 return ti_none;
5833 if(cmb_first >= selection_first && cmb_last <= selection_last)
5834 return ti_encompass;
5835
5836 do
5837 {
5838 if(cmb.tile+offset >= selection_first && cmb.tile+offset <= selection_last)
5839 {
5840 reset_combo_animation(cmb);
5841 return ti_broken; //contained, but non-encompassing.
5842 }
5843 animate(cmb, true);
5844 }
5845 while(cmb.tile != cmb.o_tile);
5846 reset_combo_animation(cmb);
5847 return ti_none;
5848 }
5849 int32_t move_intersection_ss(int32_t check_first, int32_t check_last, int32_t selection_first, int32_t selection_last)
5850 {
5851 // if selection is before or after check...
5852 if((check_first>selection_last)||(selection_first>check_last))
5853 {
5854 return ti_none;
5855 }
5856
5857 // if selection envelopes check
5858 if((selection_first<=check_first)&&(selection_last>=check_last))
5859 {
5860 return ti_encompass; //encompass
5861 }
5862
5863 //everything else is a break
5864 return ti_broken; //intersect
5865 }
5866
5867
5868
5869 //rectangular check and striped selection
5870 int32_t move_intersection_rs(int32_t check_left, int32_t check_top, int32_t check_width, int32_t check_height, int32_t selection_first, int32_t selection_last)
5871 {
5872 int32_t ret1=-1, ret2=-1;
5873
5874 for(int32_t i=0; i<check_height; ++i)
5875 {
5876 int32_t check_first=((check_top+i)*TILES_PER_ROW)+check_left;
5877 int32_t check_last=check_first+check_width-1;
5878 ret2=move_intersection_ss(check_first, check_last, selection_first, selection_last);
5879
5880 if(ret2==ti_broken)
5881 {
5882 return ti_broken;
5883 }
5884
5885 ret1=(ret2==ti_encompass?ti_encompass:ret1);
5886 }
5887
5888 if(ret1==ti_encompass)
5889 {
5890 if((TILEROW(selection_first)<=check_top) &&
5891 (TILEROW(selection_last)>=(check_top+check_height-1)))
5892 {
5893 return ti_encompass;
5894 }
5895 else
5896 {
5897 return ti_broken;
5898 }
5899 }
5900
5901 return ti_none;
5902 }
5903
5904
5905 //striped check and rectangular selection
5906 int32_t move_intersection_sr(newcombo &cmb, int32_t selection_left, int32_t selection_top, int32_t selection_width, int32_t selection_height, int32_t offset = 0)
5907 {
5908 if(selection_width < TILES_PER_ROW)
5909 {
5910 int32_t cmb_first = cmb.o_tile;
5911 int32_t cmb_last = cmb.o_tile;
5912 do
5913 {
5914 cmb_last = cmb.tile;
5915 animate(cmb, true);
5916 }
5917 while(cmb.tile != cmb.o_tile);
5918 reset_combo_animation(cmb);
5919 cmb_first += offset;
5920 cmb_last += offset;
5921
5922 if((TILEROW(cmb_first)>=selection_top) &&
5923 (TILEROW(cmb_last)<=selection_top+selection_height-1) &&
5924 (TILECOL(cmb_first)>=selection_left) &&
5925 (TILECOL(cmb_last)<=TILECOL(selection_left+selection_width-1)))
5926 {
5927 return ti_encompass;
5928 }
5929 else if((cmb_last<selection_top*TILES_PER_ROW+selection_left) ||
5930 (cmb_first>(selection_top+selection_height-1)*TILES_PER_ROW+selection_left+selection_width-1))
5931 {
5932 return ti_none;
5933 }
5934
5935 if(TILEROW(cmb_first) == TILEROW(cmb_last))
5936 {
5937 int32_t firstcol = TILECOL(cmb_first);
5938 int32_t lastcol = TILECOL(cmb_last);
5939
5940 if(lastcol < selection_left || firstcol >= selection_left+selection_width)
5941 return ti_none;
5942 else //handle skip x
5943 {
5944 do
5945 {
5946 if(TILECOL(cmb.tile) >= selection_left && TILECOL(cmb.tile) <= selection_left+selection_width)
5947 {
5948 reset_combo_animation(cmb);
5949 return ti_broken;
5950 }
5951 animate(cmb, true);
5952 }
5953 while(cmb.tile != cmb.o_tile);
5954 reset_combo_animation(cmb);
5955 return ti_none;
5956 }
5957 }
5958 else //multi-row combo...
5959 {
5960 int32_t row = TILEROW(cmb_first);
5961
5962 do
5963 {
5964 if(row < selection_top || row > selection_top+selection_height-1)
5965 {
5966 //This row isn't in the selection; skip to next row
5967 do
5968 {
5969 animate(cmb,true);
5970 if(cmb.tile == cmb.o_tile) return ti_none; //reached end
5971 }
5972 while(TILEROW(cmb.tile) == row);
5973 row = TILEROW(cmb.tile);
5974 continue;
5975 }
5976
5977 //This row IS in the selection; check each tile.
5978 do
5979 {
5980 if(TILECOL(cmb.tile) >= selection_left && TILECOL(cmb.tile) <= selection_left+selection_width-1)
5981 {
5982 reset_combo_animation(cmb);
5983 return ti_broken;
5984 }
5985 animate(cmb, true);
5986 if(cmb.tile == cmb.o_tile) return ti_none; //reached end
5987 }
5988 while(TILEROW(cmb.tile) == row);
5989 row = TILEROW(cmb.tile);
5990 }
5991 while(cmb.tile != cmb.o_tile);
5992
5993 return ti_none; //...Theoretically unreachable, but if it DOES get here, it's done.
5994 }
5995 }
5996
5997 return move_intersection_ss(cmb, selection_top*TILES_PER_ROW+selection_left, (selection_top+selection_height-1)*TILES_PER_ROW+selection_left+selection_width-1, offset);
5998 }
5999 int32_t move_intersection_sr(int32_t check_first, int32_t check_last, int32_t selection_left, int32_t selection_top, int32_t selection_width, int32_t selection_height)
6000 {
6001 if(selection_width < TILES_PER_ROW)
6002 {
6003 if((check_last-check_first+1<=selection_width) &&
6004 (TILEROW(check_first)>=selection_top) &&
6005 (TILEROW(check_last)<=selection_top+selection_height-1) &&
6006 (TILECOL(check_first)>=selection_left) &&
6007 (TILECOL(check_last)<=TILECOL(selection_left+selection_width-1)))
6008 {
6009 return ti_encompass;
6010 }
6011 else if((check_last<selection_top*TILES_PER_ROW+selection_left) ||
6012 (check_first>(selection_top+selection_height-1)*TILES_PER_ROW+selection_left+selection_width-1))
6013 {
6014 return ti_none;
6015 }
6016
6017 //else if (selection_top*TILES_PER_ROW+selection_left<check_first && (selection_top+1)*TILES_PER_ROW+selection_left>check_last)
6018
6019 //one last base case: the strip we're interested in only lies along one row
6020 if(check_first/TILES_PER_ROW == check_last/TILES_PER_ROW)
6021 {
6022 int32_t cfcol = check_first%TILES_PER_ROW;
6023 int32_t clcol = check_last%TILES_PER_ROW;
6024
6025 if(clcol < selection_left || cfcol >= selection_left+selection_width)
6026 return ti_none;
6027 else
6028 return ti_broken;
6029 }
6030 else
6031 {
6032 //recursively cut the strip into substrips which lie entirely on one row
6033 int32_t currow = check_first/TILES_PER_ROW;
6034 int32_t endrow = check_last/TILES_PER_ROW;
6035 int32_t accum = 0;
6036 accum |= move_intersection_sr(check_first,(currow+1)*TILES_PER_ROW-1,selection_left,selection_top,selection_width,selection_height);
6037
6038 for(++currow; currow<endrow; currow++)
6039 {
6040 accum |= move_intersection_sr(currow*TILES_PER_ROW,(currow+1)*TILES_PER_ROW-1,selection_left,selection_top,selection_width,selection_height);
6041 }
6042
6043 accum |= move_intersection_sr(currow*TILES_PER_ROW, check_last,selection_left,selection_top,selection_width,selection_height);
6044
6045 if(accum > 0)
6046 return ti_broken;
6047
6048 return ti_none;
6049 }
6050 }
6051
6052 return move_intersection_ss(check_first, check_last, selection_top*TILES_PER_ROW+selection_left, (selection_top+selection_height-1)*TILES_PER_ROW+selection_left+selection_width-1);
6053 }
6054
6055 //rectangular check and rectangular selection
6056 int32_t move_intersection_rr(int32_t check_left, int32_t check_top, int32_t check_width, int32_t check_height, int32_t selection_left, int32_t selection_top, int32_t selection_width, int32_t selection_height)
6057 {
6058 if((check_left>=selection_left) &&
6059 (check_left+check_width<=selection_left+selection_width) &&
6060 (check_top>=selection_top) &&
6061 (check_top+check_height<=selection_top+selection_height))
6062 {
6063 return ti_encompass;
6064 }
6065 else
6066 {
6067 for(int32_t i=check_top; i<check_top+check_height; ++i)
6068 {
6069 if(move_intersection_rs(selection_left, selection_top, selection_width, selection_height, i*TILES_PER_ROW+check_left, i*TILES_PER_ROW+check_left+check_width-1)!=ti_none)
6070 {
6071 return ti_broken;
6072 }
6073 }
6074 }
6075
6076 return ti_none;
6077 }
6078
6079
6080
6081
6082 static DIALOG move_textbox_list_dlg[] =
6083 {
6084 // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp)
6085 9 { jwin_win_proc, 0, 0, 300, 212, vc(14), vc(1), 0, D_EXIT, 0, 0, NULL, NULL, NULL },
6086 9 { jwin_ctext_proc, 150, 18, 0, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "", NULL, NULL },
6087 9 { jwin_ctext_proc, 150, 28, 0, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "", NULL, NULL },
6088 9 { jwin_textbox_proc, 12, 40, 277, 138, jwin_pal[jcTEXTFG], jwin_pal[jcTEXTBG], 0, D_EXIT, 0, 0, NULL, NULL, NULL },
6089 9 { jwin_button_proc, 80, 185, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
6090 9 { jwin_button_proc, 160, 185, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
6091 9 { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
6092 9 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
6093 };
6094
6095 bool popup_move_textbox_dlg(string const& msg, char* textbox, char const* title)
6096 {
6097 char buf1[512] = {0};
6098 char buf2[512] = {0};
6099 large_dialog(move_textbox_list_dlg);
6100 DIALOG& tbox = move_textbox_list_dlg[3];
6101 {
6102 FONT* f = tbox.dp2 ? (FONT*)tbox.dp2 : get_custom_font(CFONT_GUI);
6103 int indx = 0, word_indx = 0;
6104 for(char c : msg)
6105 {
6106 if(c == ' ' || c == '\n')
6107 word_indx = indx;
6108 buf1[indx++] = c;
6109 if(c == '\n' || text_length(f, buf1) >= tbox.w)
6110 {
6111 buf1[word_indx] = 0;
6112 strcpy(buf2, msg.c_str()+word_indx+1);
6113 break;
6114 }
6115 }
6116 }
6117
6118 move_textbox_list_dlg[0].dp = (void*)title;
6119 move_textbox_list_dlg[0].dp2 = get_zc_font(font_lfont);
6120 move_textbox_list_dlg[1].dp = buf1;
6121 move_textbox_list_dlg[2].dp = buf2;
6122 tbox.dp = textbox;
6123 tbox.d2 = 0;
6124 auto tby = tbox.y;
6125 auto tbh = tbox.h;
6126 if(!buf2[0])
6127 {
6128 auto diff = move_textbox_list_dlg[2].h;
6129 tbox.y -= diff;
6130 tbox.h += diff;
6131 }
6132
6133 int32_t ret=do_zqdialog(move_textbox_list_dlg,2);
6134 position_mouse_z(0);
6135 tbox.y = tby;
6136 tbox.h = tbh;
6137
6138 return ret == 4;
6139 }
6140
6141 int32_t quick_select_3(int32_t a, int32_t b, int32_t c, int32_t d)
6142 {
6143 return a==0?b:a==1?c:d;
6144 }
6145
6146 bool TileMoveList::process(std::unique_ptr<BaseTileRef>& ref, TileMoveProcess const& proc, bool is_dest)
6147 {
6148 TileRefCombo* combo_ref = dynamic_cast<TileRefCombo*>(ref.get());
6149 int i = ti_none;
6150 auto t = ref->getTile() + ref->offset();
6151
6152 if(combo_ref)
6153 {
6154 if(proc.rect)
6155 i=move_intersection_sr(*combo_ref->combo, proc._l, proc._t, proc._w, proc._h);
6156 else i=move_intersection_ss(*combo_ref->combo, proc._first, proc._last);
6157 }
6158 else if(proc.rect)
6159 {
6160 if(ref->h > 1)
6161 i=move_intersection_rr(TILECOL(t), TILEROW(t), ref->w, ref->h, proc._l, proc._t, proc._w, proc._h);
6162 else i=move_intersection_sr(t, t+ref->w-1, proc._l, proc._t, proc._w, proc._h);
6163 }
6164 else
6165 {
6166 if(ref->h > 1)
6167 i=move_intersection_rs(TILECOL(t), TILEROW(t), ref->w, ref->h, proc._first, proc._last);
6168 else i=move_intersection_ss(t, t+ref->w-1, proc._first, proc._last);
6169 }
6170
6171 bool in = i != ti_none, out = i != ti_encompass;
6172 for(size_t q = 0; !(in&&out) && q < ref->extra_rects.size(); ++q)
6173 {
6174 auto [ex_t,ex_w,ex_h] = ref->extra_rects[q];
6175 if(proc.rect)
6176 i = move_intersection_rr(TILECOL(t+ex_t), TILEROW(t+ex_t), ex_w, ex_h, proc._l, proc._t, proc._w, proc._h);
6177 else i = move_intersection_rs(TILECOL(t+ex_t), TILEROW(t+ex_t), ex_w, ex_h, proc._first, proc._last);
6178 if(i != ti_none)
6179 in = true;
6180 if(i != ti_encompass)
6181 out = true;
6182 }
6183 i = in ? (out ? ti_broken : ti_encompass) : ti_none;
6184
6185 if(i != ti_none && ref->getTile() != 0)
6186 {
6187 if(mode == Mode::CHECK_ALL)
6188 {
6189 move_refs.emplace_back(std::move(ref));
6190 return true;
6191 }
6192 else if(i==ti_broken || is_dest || (i==ti_encompass && ref->no_move))
6193 {
6194 if(warning_flood || warning_list.tellp() >= 65000)
6195 {
6196 if(!warning_flood)
6197 warning_list << "...\n...\n...\nmany others";
6198 warning_flood = true;
6199 }
6200 else
6201 warning_list << ref->name << '\n';
6202 }
6203 else if(i==ti_encompass)
6204 {
6205 move_refs.emplace_back(std::move(ref));
6206 return true;
6207 }
6208 }
6209 return false;
6210 }
6211
6212 bool TileMoveList::check_prot()
6213 {
6214 if(!TileProtection)
6215 return true;
6216 auto ret = !warning_list.tellp() || popup_move_textbox_dlg(msg, warning_list.str().data(), "Tile Warning");
6217
6218 warning_flood = false;
6219 warning_list.clear();
6220
6221 return ret;
6222 }
6223
6224 void TileMoveList::add_diff(int diff)
6225 {
6226 for(auto& ref : move_refs)
6227 ref->addTile(diff);
6228 }
6229
6230 //from 'combo.h'
6231 bool ComboMoveList::process(std::unique_ptr<BaseComboRef>& ref, ComboMoveProcess const& proc, bool is_dest)
6232 {
6233 int i = ti_none;
6234 auto c = ref->getCombo();
6235
6236 if(ref->no_move)
6237 processed_combos[c] = true;
6238 else processed_combos[c]; //inserts element if does not exist
6239 i = move_intersection_ss(c, c, proc._first, proc._last);
6240
6241 if(i != ti_none && ref->getCombo() != 0)
6242 {
6243 if(i==ti_broken || is_dest || (i==ti_encompass && ref->no_move))
6244 {
6245 if(ComboProtection)
6246 {
6247 if(warning_flood || warning_list.tellp() >= 65000)
6248 {
6249 if(!warning_flood)
6250 warning_list << "...\n...\n...\nmany others";
6251 warning_flood = true;
6252 }
6253 else
6254 warning_list << ref->name << '\n';
6255 }
6256 }
6257 else if(i==ti_encompass)
6258 {
6259 move_refs.emplace_back(std::move(ref));
6260 return true;
6261 }
6262 }
6263 return false;
6264 }
6265
6266 bool ComboMoveList::check_prot()
6267 {
6268 if(!ComboProtection)
6269 return true;
6270 vector<set<int> const*> subset = combo_links.subset(processed_combos);
6271 bool subset_header = false;
6272 for(int q = 0; q < 2; ++q)
6273 {
6274 bool is_dest = (q==1);
6275 if(!is_dest && !source_process)
6276 continue;
6277 ComboMoveProcess const& proc = is_dest ? dest_process : *source_process;
6278 for(auto it = subset.begin(); it != subset.end();)
6279 {
6280 auto s = *it;
6281 if(warning_flood || warning_list.tellp() >= 65000)
6282 {
6283 if(!warning_flood)
6284 warning_list << "...\n...\n...\nmany others";
6285 warning_flood = true;
6286 break;
6287 }
6288 set<int> in_set, out_set;
6289 bool no_move = is_dest;
6290 for(int c : *s)
6291 {
6292 int i = move_intersection_ss(c, c, proc._first, proc._last);
6293 if(i != ti_none)
6294 in_set.insert(c);
6295 if(i != ti_encompass)
6296 out_set.insert(c);
6297 if(!no_move)
6298 {
6299 auto it = processed_combos.find(c);
6300 if(it != processed_combos.end() && it->second)
6301 no_move = true;
6302 }
6303 }
6304 int i = in_set.empty() ? ti_none : (out_set.empty() ? ti_encompass : ti_broken);
6305 if(i == ti_encompass && !no_move)
6306 {
6307 it = subset.erase(it);
6308 continue;
6309 }
6310 if(i == ti_none)
6311 {
6312 ++it;
6313 continue;
6314 }
6315
6316 if(!subset_header)
6317 {
6318 subset_header = true;
6319 warning_list << "===== Broken Relative Combo Groups =====\n";
6320 }
6321 bool comma = false;
6322 warning_list << "In(";
6323 for(int c : in_set)
6324 {
6325 if(comma)
6326 warning_list << ",";
6327 else comma = true;
6328 warning_list << c;
6329 }
6330 warning_list << "),Out(";
6331 comma = false;
6332 for(int c : out_set)
6333 {
6334 if(comma)
6335 warning_list << ",";
6336 else comma = true;
6337 warning_list << c;
6338 }
6339 warning_list << ")\n";
6340 it = subset.erase(it);
6341 }
6342 }
6343 auto ret = !warning_list.tellp() || popup_move_textbox_dlg(msg, warning_list.str().data(), "Combo Warning");
6344
6345 processed_combos.clear();
6346 warning_flood = false;
6347 warning_list.clear();
6348
6349 return ret;
6350 }
6351
6352 void ComboMoveList::add_diff(int diff)
6353 {
6354 for(auto& ref : move_refs)
6355 ref->addCombo(diff);
6356 }
6357
6358 static void collect_subscreen_tiles(SubscrWidget& widget, TileMoveList& list)
6359 {
6360 if (auto w = dynamic_cast<SW_2x2Frame*>(&widget))
6361 {
6362 list.add_tile(&w->tile, 2, 2, "2x2 Frame");
6363 }
6364 else if (auto w = dynamic_cast<SW_TriFrame*>(&widget))
6365 {
6366 list.add_tile(&w->frame_tile, 6, 3, "McGuffin Frame - Frame");
6367 list.add_tile(&w->piece_tile, "McGuffin Frame - Piece");
6368 }
6369 else if (auto w = dynamic_cast<SW_McGuffin*>(&widget))
6370 {
6371 list.add_tile(&w->tile, "McGuffin Piece");
6372 }
6373 else if (auto w = dynamic_cast<SW_TileBlock*>(&widget))
6374 {
6375 list.add_tile(&w->tile, w->w, w->h, "TileBlock");
6376 }
6377 else if (auto w = dynamic_cast<SW_MiniTile*>(&widget))
6378 {
6379 if (w->tile == -1)
6380 return;
6381
6382 list.add_tile(&w->tile, "MiniTile");
6383 }
6384 else if (auto w = dynamic_cast<SW_GaugePiece*>(&widget))
6385 {
6386 int fr = w->frames ? w->frames : 1;
6387 fr = fr * (1+(w->get_per_container()/(w->unit_per_frame+1)));
6388 if(!(w->flags&SUBSCR_GAUGE_FULLTILE))
6389 fr = (fr/4_zf).getCeil();
6390
6391 for(auto q = 0; q < 4; ++q)
6392 {
6393 list.add_tile(&w->mts[q].mt_tile, fr, 1, fmt::format("Gauge Tile {}", q));
6394 }
6395 }
6396 }
6397
6398 static void collect_subscreen_tiles(SubscrPage& page, TileMoveList& list)
6399 {
6400 for(auto q = 0; q < page.contents.size(); ++q)
6401 {
6402 size_t indx = list.move_refs.size();
6403 collect_subscreen_tiles(*page.contents[q], list);
6404 for(; indx < list.move_refs.size(); ++indx)
6405 {
6406 auto& ref = list.move_refs[indx];
6407 ref->name = fmt::format("Widget {} - {}", q, ref->name);
6408 }
6409 }
6410 }
6411
6412 static void collect_subscreen_tiles(ZCSubscreen& subscreen, TileMoveList& list)
6413 {
6414 for (auto q = 0; q < subscreen.pages.size(); ++q)
6415 {
6416 size_t indx = list.move_refs.size();
6417 collect_subscreen_tiles(subscreen.pages[q], list);
6418 for(; indx < list.move_refs.size(); ++indx)
6419 {
6420 auto& ref = list.move_refs[indx];
6421 ref->name = fmt::format("Page {} - {}", q, ref->name);
6422 }
6423 }
6424 }
6425
6426 bool _handle_tile_move(TileMoveProcess dest_process, optional<TileMoveProcess> source_process, int diff, TileMoveUndo* on_undo = nullptr, std::function<void(int32_t)> every_proc = nullptr, TileMoveList::Mode mode = TileMoveList::Mode::MOVE)
6427 {
6428 bool BSZ2 = get_qr(qr_BSZELDA);
6429 bool move = source_process.has_value();
6430 TileMoveUndo local_undo;
6431 TileMoveUndo& storage = on_undo ? *on_undo : local_undo;
6432 auto& vec = storage.vec;
6433 storage.diff = diff;
6434 storage.state = false;
6435
6436 //Combos
6437 {
6438 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6439 dest_process, source_process, mode,
6440 move
6441 ? "The tiles used by the following combos will be partially cleared by the move."
6442 : "The tiles used by the following combos will be partially or completely overwritten by this process."
6443 ));
6444 for(int32_t q = 0; q < MAXCOMBOS; ++q)
6445 {
6446 auto& cmb = combobuf[q];
6447 auto lbl = fmt::format("Combo {}{}", q, cmb.label.empty() ? ""
6448 : fmt::format(" ({})", cmb.label));
6449 movelist->add_combo(&cmb, lbl);
6450
6451 //type-specific
6452 char const* type_name = ZI.getComboTypeName(cmb.type);
6453 switch(cmb.type)
6454 {
6455 case cSPOTLIGHT:
6456 {
6457 if(!(cmb.usrflags & cflag1))
6458 break;
6459 movelist->add_tile_10k(&cmb.attributes[0], 16, 1, fmt::format("{} - Type '{}' - Beam Tiles", lbl, type_name));
6460 break;
6461 }
6462 }
6463 }
6464 if(!every_proc && !movelist->check_prot())
6465 return false;
6466 }
6467 //Items
6468 {
6469 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6470 dest_process, source_process, mode,
6471 move
6472 ? "The tiles used by the following items will be partially cleared by the move."
6473 : "The tiles used by the following items will be partially or completely overwritten by this process."
6474 ));
6475 build_bii_list(false);
6476 for(int32_t u=0; u<MAXITEMS; u++)
6477 {
6478 auto id = bii[u].i;
6479 itemdata& itm = itemsbuf[id];
6480 if(itm.family == itype_bottle)
6481 {
6482 vector<std::tuple<int,int,int>> rects;
6483 auto fr = itm.frames;
6484 for(int q = 0; q < NUM_BOTTLE_TYPES; ++q)
6485 {
6486 bottletype const& bt = QMisc.bottle_types[q];
6487 if(bt.is_blank())
6488 continue;
6489 rects.emplace_back(fr+q*fr, fr, 1);
6490 }
6491 movelist->add_tile(&itm.tile, fr, 1, fmt::format("Item {}", id),
6492 false, 0, 0, rects);
6493 }
6494 else movelist->add_tile(&itm.tile, itm.frames, 1, fmt::format("Item {}", id));
6495 }
6496 if(!every_proc && !movelist->check_prot())
6497 return false;
6498 }
6499 //Weapon sprites
6500 {
6501 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6502 dest_process, source_process, mode,
6503 move
6504 ? "The tiles used by the following weapons will be partially cleared by the move."
6505 : "The tiles used by the following weapons will be partially or completely overwritten by this process."
6506 ));
6507 build_biw_list();
6508
6509 for(int32_t u=0; u<MAXWPNS; u++)
6510 {
6511 bool ignore_frames=false;
6512 int32_t m=0;
6513
6514 auto id = biw[u].i;
6515 auto& wpn = wpnsbuf[id];
6516
6517 switch(biw[u].i)
6518 {
6519 case wSWORD:
6520 case wWSWORD:
6521 case wMSWORD:
6522 case wXSWORD:
6523 m=3+((wpnsbuf[biw[u].i].type==3)?1:0);
6524 break;
6525
6526 case wSWORDSLASH:
6527 case wWSWORDSLASH:
6528 case wMSWORDSLASH:
6529 case wXSWORDSLASH:
6530 m=4;
6531 break;
6532
6533 case iwMMeter:
6534 m=9;
6535 break;
6536
6537 case wBRANG:
6538 case wMBRANG:
6539 case wFBRANG:
6540 m=BSZ2?1:3;
6541 break;
6542
6543 case wBOOM:
6544 case wSBOOM:
6545 case ewBOOM:
6546 case ewSBOOM:
6547 ignore_frames=true;
6548 m=2;
6549 break;
6550
6551 case wWAND:
6552 m=1;
6553 break;
6554
6555 case wMAGIC:
6556 m=1;
6557 break;
6558
6559 case wARROW:
6560 case wSARROW:
6561 case wGARROW:
6562 case ewARROW:
6563 m=1;
6564 break;
6565
6566 case wHAMMER:
6567 m=8;
6568 break;
6569
6570 case wHSHEAD:
6571 m=1;
6572 break;
6573
6574 case wHSCHAIN_H:
6575 m=1;
6576 break;
6577
6578 case wHSCHAIN_V:
6579 m=1;
6580 break;
6581
6582 case wHSHANDLE:
6583 m=1;
6584 break;
6585
6586 case iwDeath:
6587 if(get_qr(qr_HARDCODED_ENEMY_ANIMS))
6588 {
6589 ignore_frames = true;
6590 m=BSZ2?4:2;
6591 }
6592 break;
6593
6594 case iwSpawn:
6595 if(get_qr(qr_HARDCODED_ENEMY_ANIMS))
6596 {
6597 ignore_frames = true;
6598 m=3;
6599 }
6600 break;
6601 }
6602
6603 movelist->add_tile(&wpn.tile, zc_max((ignore_frames?0:wpn.frames),1)+m,
6604 1, fmt::format("{} {}", biw[u].s, id));
6605
6606 //Tile 54+55 are "Impact (not shown in sprite list)", for u==3 "Arrow" and u==9 "Boomerang"
6607 //...these can't be updated by a move.
6608 if((u==3)||(u==9))
6609 {
6610 static int32_t impact_tiles[2] = {54,54};
6611 auto& tile = impact_tiles[u==3 ? 0 : 1];
6612 tile = 54; //dummy tile, ensure it's correct
6613 movelist->add_tile(&tile, 2, 1,
6614 fmt::format("{} Impact (not shown in sprite list)",(u==3)?"Arrow":"Boomerang"),
6615 true);
6616 }
6617 }
6618 if(!every_proc && !movelist->check_prot())
6619 return false;
6620 }
6621 //Hero sprites
6622 {
6623 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6624 dest_process, source_process, mode,
6625 move
6626 ? "The tiles used by the following Hero sprites will be partially cleared by the move."
6627 : "The tiles used by the following Hero sprites will be partially or completely overwritten by this process."
6628 ));
6629 {
6630 int32_t a_style=(zinit.heroAnimationStyle);
6631 #define ADD_HERO_SPRITE(ref_sprite, frames, name) \
6632 do \
6633 { \
6634 movelist->add_tile(&ref_sprite[spr_tile], \
6635 (ref_sprite[spr_extend] < 2 ? 1 : 2) * frames, \
6636 ref_sprite[spr_extend] < 1 ? 1 : 2, \
6637 name, false, \
6638 ref_sprite[spr_extend] < 2 ? 0 : -1, \
6639 ref_sprite[spr_extend] < 1 ? 0 : -1); \
6640 } while(false)
6641 // + (ref_sprite[spr_extend] < 2 ? 0 : 1) //this was on some of the 'width's before... but doesn't make sense?
6642
6643 for(int32_t i=0; i<4; ++i)
6644 {
6645 ADD_HERO_SPRITE(walkspr[i], quick_select_3(a_style, (i==0?1:2), 3, 9), fmt::format("Walking ({})", dirstr_proper[i]));
6646 }
6647
6648 for(int32_t i=0; i<4; ++i)
6649 {
6650 ADD_HERO_SPRITE(slashspr[i], quick_select_3(a_style, 1, 1, 6), fmt::format("Slashing ({})", dirstr_proper[i]));
6651 }
6652
6653 for(int32_t i=0; i<4; ++i)
6654 {
6655 ADD_HERO_SPRITE(stabspr[i], quick_select_3(a_style, 1, 1, 3), fmt::format("Stabbing ({})", dirstr_proper[i]));
6656 }
6657
6658 for(int32_t i=0; i<4; ++i)
6659 {
6660 ADD_HERO_SPRITE(poundspr[i], quick_select_3(a_style, 1, 1, 3), fmt::format("Pounding ({})", dirstr_proper[i]));
6661 }
6662
6663 for(int32_t i=0; i<2; ++i)
6664 {
6665 ADD_HERO_SPRITE(holdspr[0][i], 1, fmt::format("Hold (Land, {}-hand)", i+1));
6666 }
6667
6668 ADD_HERO_SPRITE(castingspr, 1, "Casting");
6669
6670 for(int32_t i=0; i<4; ++i)
6671 {
6672 ADD_HERO_SPRITE(floatspr[i], quick_select_3(a_style, 2, 3, 4), fmt::format("Floating ({})", dirstr_proper[i]));
6673 }
6674
6675 for(int32_t i=0; i<4; ++i)
6676 {
6677 ADD_HERO_SPRITE(swimspr[i], quick_select_3(a_style, 2, 3, 4), fmt::format("Swimming ({})", dirstr_proper[i]));
6678 }
6679
6680 for(int32_t i=0; i<4; ++i)
6681 {
6682 ADD_HERO_SPRITE(divespr[i], quick_select_3(a_style, 2, 3, 4), fmt::format("Diving ({})", dirstr_proper[i]));
6683 }
6684
6685 for(int32_t i=0; i<2; ++i)
6686 {
6687 ADD_HERO_SPRITE(holdspr[1][i], 1, fmt::format("Hold (Water, {}-hand)", i));
6688 }
6689
6690 for(int32_t i=0; i<4; ++i)
6691 {
6692 ADD_HERO_SPRITE(jumpspr[i], 3, fmt::format("Jumping ({})", dirstr_proper[i]));
6693 }
6694
6695 for(int32_t i=0; i<4; ++i)
6696 {
6697 ADD_HERO_SPRITE(chargespr[i], quick_select_3(a_style, 2, 3, 9), fmt::format("Charging ({})", dirstr_proper[i]));
6698 }
6699 for(int32_t i=0; i<4; ++i)
6700 {
6701 ADD_HERO_SPRITE(revslashspr[i], quick_select_3(a_style, 1, 1, 6), fmt::format("Slash 2 ({})", dirstr_proper[i]));
6702 }
6703 for(int32_t i=0; i<4; ++i)
6704 {
6705 ADD_HERO_SPRITE(fallingspr[i], 7, fmt::format("Falling ({})", dirstr_proper[i]));
6706 }
6707 for(int32_t i=0; i<4; ++i)
6708 {
6709 ADD_HERO_SPRITE(liftingspr[i], liftingspr[i][spr_frames], fmt::format("Lifting ({})", dirstr_proper[i]));
6710 }
6711 for(int32_t i=0; i<4; ++i)
6712 {
6713 ADD_HERO_SPRITE(liftingwalkspr[i], quick_select_3(a_style, (i==0?1:2), 3, 9), fmt::format("Lift-Walking ({})", dirstr_proper[i]));
6714 }
6715 for(int32_t i=0; i<4; ++i)
6716 {
6717 ADD_HERO_SPRITE(drowningspr[i], quick_select_3(a_style, 2, 3, 3), fmt::format("Drowning ({})", dirstr_proper[i]));
6718 }
6719 for(int32_t i=0; i<4; ++i)
6720 {
6721 ADD_HERO_SPRITE(drowning_lavaspr[i], quick_select_3(a_style, 2, 3, 3), fmt::format("Lava Drowning ({})", dirstr_proper[i]));
6722 }
6723 for(int32_t i=0; i<4; ++i)
6724 {
6725 ADD_HERO_SPRITE(sideswimspr[i], quick_select_3(a_style, 2, 3, 3), fmt::format("Side-Swimming ({})", dirstr_proper[i]));
6726 }
6727 //69
6728 for(int32_t i=0; i<4; ++i)
6729 {
6730 ADD_HERO_SPRITE(sideswimslashspr[i], quick_select_3(a_style, 1, 1, 6), fmt::format("Side-Swim Slash ({})", dirstr_proper[i]));
6731 }
6732 //73
6733 for(int32_t i=0; i<4; ++i)
6734 {
6735 ADD_HERO_SPRITE(sideswimstabspr[i], quick_select_3(a_style, 1, 1, 3), fmt::format("Side-Swim Stab ({})", dirstr_proper[i]));
6736 }
6737 //77
6738 for(int32_t i=0; i<4; ++i)
6739 {
6740 ADD_HERO_SPRITE(sideswimpoundspr[i], quick_select_3(a_style, 1, 1, 3), fmt::format("Side-Swim Pound ({})", dirstr_proper[i]));
6741 }
6742 //81
6743 for(int32_t i=0; i<4; ++i)
6744 {
6745 ADD_HERO_SPRITE(sideswimchargespr[i], quick_select_3(a_style, 2, 3, 9), fmt::format("Side-Swim Charging ({})", dirstr_proper[i]));
6746 }
6747 //85
6748 ADD_HERO_SPRITE(sideswimholdspr[spr_hold1], 1, "Hold (Side-Water, 1-hand)");
6749 ADD_HERO_SPRITE(sideswimholdspr[spr_hold2], 1, "Hold (Side-Water, 2-hand)");
6750 ADD_HERO_SPRITE(sideswimcastingspr, 1, "Side-Swim Casting");
6751 for(int32_t i=0; i<4; ++i)
6752 {
6753 ADD_HERO_SPRITE(sidedrowningspr[i], quick_select_3(a_style, 2, 3, 3), fmt::format("Side-Swim Drowning ({})", dirstr_proper[i]));
6754 }
6755 //91
6756 }
6757 if(!every_proc && !movelist->check_prot())
6758 return false;
6759 }
6760 //Map Styles
6761 {
6762 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6763 dest_process, source_process, mode,
6764 move
6765 ? "The tiles used by the following map styles will be partially cleared by the move."
6766 : "The tiles used by the following map styles will be partially or completely overwritten by this process."
6767 ));
6768 movelist->add_tile(&QMisc.colors.blueframe_tile, 2, 2, "Frame");
6769 movelist->add_tile(&QMisc.colors.HCpieces_tile, zinit.hcp_per_hc, 1, "Heart Container Piece");
6770 movelist->add_tile(&QMisc.colors.triforce_tile, BSZ2?2:1, BSZ2?3:1, "McGuffin Fragment");
6771 movelist->add_tile(&QMisc.colors.triframe_tile, BSZ2?7:6, BSZ2?7:3, "McGuffin Frame");
6772 movelist->add_tile(&QMisc.colors.overworld_map_tile, 5, 3, "Overworld Map");
6773 movelist->add_tile(&QMisc.colors.dungeon_map_tile, 5, 3, "Dungeon Map");
6774 if(!every_proc && !movelist->check_prot())
6775 return false;
6776 }
6777 //Game Icons
6778 {
6779 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6780 dest_process, source_process, mode,
6781 move
6782 ? "The tiles used by the following game icons will be partially cleared by the move."
6783 : "The tiles used by the following game icons will be partially or completely overwritten by this process."
6784 ));
6785 for(int32_t u=0; u<4; u++)
6786 movelist->add_tile(&QMisc.icons[u], fmt::format("Game Icon {}", u));
6787 if(!every_proc && !movelist->check_prot())
6788 return false;
6789 }
6790 //DMaps
6791 {
6792 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6793 dest_process, source_process, mode,
6794 move
6795 ? "The tiles used by the following dmaps will be partially cleared by the move."
6796 : "The tiles used by the following dmaps will be partially or completely overwritten by this process."
6797 ));
6798 for(int32_t u=0; u<MAXDMAPS; u++)
6799 {
6800 auto& dm = DMaps[u];
6801 movelist->add_tile(&dm.minimap_1_tile, 5, 3, fmt::format("DMap {} - Minimap (Empty)", u));
6802 movelist->add_tile(&dm.minimap_2_tile, 5, 3, fmt::format("DMap {} - Minimap (Filled)", u));
6803 movelist->add_tile(&dm.largemap_1_tile, BSZ2?7:9, 5, fmt::format("DMap {} - Large Map (Empty)", u));
6804 movelist->add_tile(&dm.largemap_2_tile, BSZ2?7:9, 5, fmt::format("DMap {} - Large Map (Filled)", u));
6805 }
6806 if(!every_proc && !movelist->check_prot())
6807 return false;
6808 }
6809 //Enemies
6810 {
6811 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6812 dest_process, source_process, mode,
6813 move
6814 ? "The tiles used by the following enemies will be partially cleared by the move."
6815 : "The tiles used by the following enemies will be partially or completely overwritten by this process."
6816 ));
6817 build_bie_list(false);
6818 bool newtiles=get_qr(qr_NEWENEMYTILES)!=0;
6819 for(int u=0; u<eMAXGUYS; u++)
6820 {
6821 guydata& enemy=guysbuf[bie[u].i];
6822 bool darknut=false;
6823 bool gleeok=false;
6824
6825 if(enemy.family==eeWALK && ((enemy.flags&(guy_shield_back|guy_shield_front|guy_shield_left|guy_shield_right))!=0))
6826 darknut=true;
6827 else if(enemy.family==eeGLEEOK)
6828 gleeok=true;
6829 else if (enemy.family == eePATRA)
6830 {
6831 if (!get_qr(qr_PATRAS_USE_HARDCODED_OFFSETS))
6832 {
6833 darknut=true; //uses the same logic no need for separate variables!
6834 }
6835 }
6836
6837 // Dummied out enemies
6838 if(bie[u].i>=eOCTO1S && bie[u].i<e177)
6839 {
6840 if(old_guy_string[bie[u].i][strlen(old_guy_string[bie[u].i])-1]==' ')
6841 {
6842 continue;
6843 }
6844 }
6845
6846 if(newtiles)
6847 {
6848 if(enemy.e_tile==0)
6849 {
6850 continue;
6851 }
6852
6853 vector<std::tuple<int,int,int>> rects;
6854
6855 if(darknut) //or anything that uses S. Tile for with new tiles
6856 {
6857 if (enemy.s_tile != 0)
6858 {
6859 movelist->add_tile(&enemy.s_tile, enemy.s_width, enemy.s_height, fmt::format("Enemy {} ({}) 'Special'", u, bie[u].s));
6860 }
6861 }
6862 else if (gleeok)
6863 {
6864 for (int32_t j = 0; j < enemy.attributes[4]; ++j)
6865 {
6866 rects.emplace_back(enemy.attributes[5] + (enemy.attributes[6]*j), 4, 1);
6867 }
6868 rects.emplace_back(enemy.attributes[7], 4, 1);
6869 rects.emplace_back(enemy.attributes[8], 4, 1);
6870 }
6871 movelist->add_tile(&enemy.e_tile, enemy.e_width, enemy.e_height, fmt::format("Enemy {} ({}) 'New'", u, bie[u].s),
6872 false, 0, 0, rects);
6873
6874 }
6875 else
6876 {
6877 if(enemy.tile==0)
6878 {
6879 continue;
6880 }
6881 movelist->add_tile(&enemy.tile, enemy.width, enemy.height, fmt::format("Enemy {} ({}) 'Old'", u, bie[u].s));
6882
6883 if(enemy.s_tile!=0)
6884 {
6885 movelist->add_tile(&enemy.s_tile, enemy.s_width, enemy.s_height, fmt::format("Enemy {} ({}) 'Special'", u, bie[u].s));
6886 }
6887 }
6888 }
6889 if(!every_proc && !movelist->check_prot())
6890 return false;
6891 }
6892 //Subscreens
6893 {
6894 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6895 dest_process, source_process, mode,
6896 move
6897 ? "The tiles used by the following subscreen widgets will be partially cleared by the move."
6898 : "The tiles used by the following subscreen widgets will be partially or completely overwritten by this process."
6899 ));
6900
6901 for(auto q = 0; q < subscreens_active.size(); ++q)
6902 {
6903 size_t indx = movelist->move_refs.size();
6904 collect_subscreen_tiles(subscreens_active[q], *movelist.get());
6905 for(; indx < movelist->move_refs.size(); ++indx)
6906 {
6907 auto& ref = movelist->move_refs[indx];
6908 ref->name = fmt::format("Active Subscr {} - {}", q, ref->name);
6909 }
6910 }
6911 for(auto q = 0; q < subscreens_passive.size(); ++q)
6912 {
6913 size_t indx = movelist->move_refs.size();
6914 collect_subscreen_tiles(subscreens_passive[q], *movelist.get());
6915 for(; indx < movelist->move_refs.size(); ++indx)
6916 {
6917 auto& ref = movelist->move_refs[indx];
6918 ref->name = fmt::format("Passive Subscr {} - {}", q, ref->name);
6919 }
6920 }
6921 for(auto q = 0; q < subscreens_overlay.size(); ++q)
6922 {
6923 size_t indx = movelist->move_refs.size();
6924 collect_subscreen_tiles(subscreens_overlay[q], *movelist.get());
6925 for(; indx < movelist->move_refs.size(); ++indx)
6926 {
6927 auto& ref = movelist->move_refs[indx];
6928 ref->name = fmt::format("Overlay Subscr {} - {}", q, ref->name);
6929 }
6930 }
6931 if(!every_proc && !movelist->check_prot())
6932 return false;
6933 }
6934 //Strings
6935 {
6936 auto& movelist = vec.emplace_back(std::make_unique<TileMoveList>(
6937 dest_process, source_process, mode,
6938 move
6939 ? "The tiles used by the following strings will be partially cleared by the move."
6940 : "The tiles used by the following strings will be partially or completely overwritten by this process."
6941 ));
6942 for(size_t q = 0; q < msg_count; ++q)
6943 {
6944 MsgStr& str = MsgStrings[q];
6945 bool fulltile = str.stringflags & STRINGFLAG_FULLTILE;
6946 movelist->add_tile(&str.tile, fulltile ? (str.w/16_zf).getCeil() : 2,
6947 fulltile ? (str.h/16_zf).getCeil() : 2, fmt::format("{} (BG): '{}'", q, util::snip(str.s,100)));
6948 movelist->add_tile(&str.portrait_tile, str.portrait_tw, str.portrait_th,
6949 fmt::format("{} (Port.): '{}'", q, util::snip(str.s,100)));
6950 }
6951 if(!every_proc && !movelist->check_prot())
6952 return false;
6953 }
6954
6955 if(source_process) //Apply the 'diff' value to all moved tiles
6956 storage.redo();
6957 if(every_proc)
6958 for(auto &list : vec)
6959 for(auto &ref : list->move_refs)
6960 ref->forEach(every_proc);
6961 return true;
6962 }
6963 bool handle_tile_move(TileMoveProcess dest_process)
6964 {
6965 return _handle_tile_move(dest_process, nullopt, 0);
6966 }
6967 bool handle_tile_move(TileMoveProcess dest_process, TileMoveProcess source_process, int diff, TileMoveUndo& on_undo)
6968 {
6969 return _handle_tile_move(dest_process, source_process, diff, &on_undo);
6970 }
6971 void for_every_used_tile(std::function<void(int32_t)> proc)
6972 {
6973 reset_combo_animations();
6974 reset_combo_animations2();
6975 TileMoveProcess all_tiles {.rect = false, ._first = 0, ._last = NEWMAXTILES-1};
6976 _handle_tile_move(all_tiles, nullopt, 0, nullptr, proc, TileMoveList::Mode::CHECK_ALL);
6977 }
6978
6979 bool _handle_combo_move(ComboMoveProcess dest_process, optional<ComboMoveProcess> source_process, int diff, ComboMoveUndo* on_undo)
6980 {
6981 bool BSZ2 = get_qr(qr_BSZELDA);
6982 bool move = source_process.has_value();
6983 ComboMoveUndo local_undo;
6984 ComboMoveUndo& storage = on_undo ? *on_undo : local_undo;
6985 auto& vec = storage.vec;
6986 auto& combo_links = storage.combo_links;
6987 storage.diff = diff;
6988 storage.state = false;
6989 //Combo relative links
6990 {
6991 for(int32_t q = 0; q < MAXCOMBOS; ++q)
6992 {
6993 newcombo& cmb = combobuf[q];
6994 if(cmb.trigchange)
6995 combo_links.add_to(q, q+cmb.trigchange);
6996 bool next = cmb.flag == mfSECRETSNEXT;
6997 switch(cmb.type)
6998 {
6999 case cPOUND:
7000 case cLOCKBLOCK: case cLOCKBLOCK2:
7001 case cBOSSLOCKBLOCK: case cBOSSLOCKBLOCK2:
7002 case cCHEST: case cCHEST2:
7003 case cLOCKEDCHEST: case cLOCKEDCHEST2:
7004 case cBOSSCHEST: case cBOSSCHEST2:
7005 case cSTEP: case cSTEPSAME: case cSTEPALL: case cSTEPCOPY:
7006 case cSLASHNEXT: case cSLASHNEXTITEM: case cBUSHNEXT:
7007 case cSLASHNEXTTOUCHY: case cSLASHNEXTITEMTOUCHY: case cBUSHNEXTTOUCHY:
7008 case cTALLGRASSNEXT: case cCRUMBLE:
7009 next = true;
7010 break;
7011 case cCSWITCH: case cCSWITCHBLOCK:
7012 combo_links.add_to(q, q+cmb.attributes[0]);
7013 break;
7014 case cLIGHTTARGET:
7015 if(cmb.usrflags & cflag1)
7016 combo_links.add_to(q, q-1);
7017 else next = true;
7018 break;
7019 case cSTEPSFX:
7020 if((cmb.usrflags&(cflag1|cflag3)) == cflag1)
7021 next = true;
7022 break;
7023 }
7024 if(next)
7025 combo_links.add_to(q, q+1);
7026 }
7027 }
7028
7029 //This function is expensive! Any optimizations possible should be made. -Em
7030
7031 //OPT: Check for a 0-val preemptively, to avoid processing the fmt::format strings
7032 #define ADDC(ptr, str) \
7033 if(*ptr) movelist->add_combo(ptr, ComboProtection ? str : "");
7034 #define ADDC_10k(ptr, str) \
7035 if(*ptr) movelist->add_combo_10k(ptr, ComboProtection ? str : "");
7036 //Combos
7037 {
7038 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7039 combo_links, dest_process, source_process,
7040 move
7041 ? "The combos used by the following combos will be partially cleared by the move."
7042 : "The combos used by the following combos will be partially or completely overwritten by this process."
7043 ));
7044 for(int32_t q = 0; q < MAXCOMBOS; ++q)
7045 {
7046 newcombo& cmb = combobuf[q];
7047 auto lbl = fmt::format("{}{}", q, cmb.label.empty() ? ""
7048 : fmt::format(" ({})", cmb.label));
7049 ADDC(&cmb.nextcombo, fmt::format("{} - Combo Cycle", lbl));
7050 ADDC(&cmb.liftcmb, fmt::format("{} - Lift Combo", lbl));
7051 ADDC(&cmb.liftundercmb, fmt::format("{} - Lift Undercombo", lbl));
7052 ADDC(&cmb.prompt_cid, fmt::format("{} - Triggers ButtonPrompt", lbl));
7053
7054 //type-specific
7055 char const* type_name = ZI.getComboTypeName(cmb.type);
7056 switch(cmb.type)
7057 {
7058 case cLOCKEDCHEST: case cBOSSCHEST:
7059 if(cmb.usrflags & cflag13)
7060 ADDC_10k(&cmb.attributes[2], fmt::format("{} - Type '{}' - Locked Prompt", lbl, type_name));
7061 [[fallthrough]];
7062 case cCHEST:
7063 if(cmb.usrflags & cflag13)
7064 ADDC_10k(&cmb.attributes[1], fmt::format("{} - Type '{}' - Prompt", lbl, type_name));
7065 break;
7066 case cLOCKBLOCK: case cBOSSLOCKBLOCK:
7067 if(cmb.usrflags & cflag13)
7068 {
7069 ADDC_10k(&cmb.attributes[1], fmt::format("{} - Type '{}' - Prompt", lbl, type_name));
7070 ADDC_10k(&cmb.attributes[2], fmt::format("{} - Type '{}' - Locked Prompt", lbl, type_name));
7071 }
7072 break;
7073 case cSIGNPOST:
7074 if(cmb.usrflags & cflag13)
7075 ADDC_10k(&cmb.attributes[1], fmt::format("{} - Type '{}' - Prompt", lbl, type_name));
7076 break;
7077 case cBUTTONPROMPT:
7078 if(cmb.usrflags & cflag13)
7079 ADDC_10k(&cmb.attributes[0], fmt::format("{} - Type '{}' - Prompt", lbl, type_name));
7080 break;
7081 }
7082 }
7083
7084 if(!movelist->check_prot())
7085 return false;
7086 }
7087 //Door Combo Sets
7088 {
7089 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7090 combo_links, dest_process, source_process,
7091 move
7092 ? "The combos used by the following screens will be partially cleared by the move."
7093 : "The combos used by the following screens will be partially or completely overwritten by this process."
7094 ));
7095 static const char* door_names[9] = {
7096 "Wall", "Locked", "Shuttered", "Boss", "Bombed", "Open", "Unlocked", "Open Shuttered", "Open Boss"
7097 };
7098 for(int32_t i=0; i<MAXDOORCOMBOSETS; i++)
7099 {
7100 auto& dcs = DoorComboSets[i];
7101 auto& name = DoorComboSetNames[i];
7102 for(int32_t j=0; j<9; j++)
7103 {
7104 if(j<4)
7105 {
7106 ADDC(&dcs.walkthroughcombo[j], fmt::format("{} ({}): Walk-Through {}", i, name, j));
7107
7108 if(j<3)
7109 {
7110 if(j<2)
7111 {
7112 ADDC(&dcs.bombdoorcombo_u[j], fmt::format("{} ({}): Unused? bombdoorcombo_u {}", i, name, j));
7113 ADDC(&dcs.bombdoorcombo_d[j], fmt::format("{} ({}): Unused? bombdoorcombo_d {}", i, name, j));
7114 }
7115 ADDC(&dcs.bombdoorcombo_l[j], fmt::format("{} ({}): Unused? bombdoorcombo_l {}", i, name, j));
7116 ADDC(&dcs.bombdoorcombo_r[j], fmt::format("{} ({}): Unused? bombdoorcombo_r {}", i, name, j));
7117 }
7118 }
7119
7120 for(int32_t k=0; k<6; k++)
7121 {
7122 if(k<4)
7123 {
7124 ADDC(&dcs.doorcombo_u[j][k], fmt::format("{} ({}): Top, {} #{}", i, name, door_names[j], k));
7125 ADDC(&dcs.doorcombo_d[j][k], fmt::format("{} ({}): Bottom, {} #{}", i, name, door_names[j], k));
7126 }
7127
7128 ADDC(&dcs.doorcombo_l[j][k], fmt::format("{} ({}): Left, {} #{}", i, name, door_names[j], k));
7129 ADDC(&dcs.doorcombo_r[j][k], fmt::format("{} ({}): Right, {} #{}", i, name, door_names[j], k));
7130 }
7131 }
7132 }
7133
7134 if(!movelist->check_prot())
7135 return false;
7136 }
7137 //Combo Pools
7138 {
7139 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7140 combo_links, dest_process, source_process,
7141 move
7142 ? "The combos used by the following combo pools will be partially cleared by the move."
7143 : "The combos used by the following combo pools will be partially or completely overwritten by this process."
7144 ));
7145 for(auto q = 0; q < MAXCOMBOPOOLS; ++q)
7146 {
7147 combo_pool& pool = combo_pools[q];
7148 int idx = 0;
7149 for(cpool_entry& cp : pool.combos)
7150 ADDC(&cp.cid, fmt::format("{} index {}", q, idx++));
7151 }
7152
7153 if(!movelist->check_prot())
7154 return false;
7155 }
7156 //Auto Combos
7157 {
7158 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7159 combo_links, dest_process, source_process,
7160 move
7161 ? "The combos used by the following autocombos will be partially cleared by the move."
7162 : "The combos used by the following autocombos will be partially or completely overwritten by this process."
7163 ));
7164 for (auto q = 0; q < MAXAUTOCOMBOS; ++q)
7165 {
7166 combo_auto& cauto = combo_autos[q];
7167 int idx = 0;
7168 for (autocombo_entry& ac : cauto.combos)
7169 ADDC(&ac.cid, fmt::format("{} index {}", q, idx++));
7170 ADDC(&cauto.cid_erase, fmt::format("{} Erase Combo", q));
7171 ADDC(&cauto.cid_display, fmt::format("{} Display Combo", q));
7172 }
7173
7174 if(!movelist->check_prot())
7175 return false;
7176 }
7177 //Combo Aliases
7178 {
7179 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7180 combo_links, dest_process, source_process,
7181 move
7182 ? "The combos used by the following aliases will be partially cleared by the move."
7183 : "The combos used by the following aliases will be partially or completely overwritten by this process."
7184 ));
7185 for(int32_t i=0; i<MAXCOMBOALIASES; i++)
7186 {
7187 //dimensions are 1 less than you would expect -DD
7188 int32_t count=(comboa_lmasktotal(combo_aliases[i].layermask)+1)*(combo_aliases[i].width+1)*(combo_aliases[i].height+1);
7189
7190 for(int32_t j=0; j<count; j++)
7191 {
7192 ADDC(&combo_aliases[i].combos[j], fmt::format("{} index {}", i, j));
7193 }
7194 }
7195
7196 if(!movelist->check_prot())
7197 return false;
7198 }
7199 //Favorite Combos
7200 {
7201 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7202 combo_links, dest_process, source_process,
7203 move
7204 ? "The combos used by the following favorite combos will be partially cleared by the move."
7205 : "The combos used by the following favorite combos will be partially or completely overwritten by this process."
7206 ));
7207 for(int32_t i=0; i<MAXFAVORITECOMBOS; i++)
7208 {
7209 if(favorite_combo_modes[i] != dm_normal) //don't hit pools/aliases/autos, only combos!
7210 continue;
7211 ADDC(&favorite_combos[i], fmt::format("Favorite {}", i));
7212 }
7213
7214 if(!movelist->check_prot())
7215 return false;
7216 }
7217 //Bottle Shops
7218 {
7219 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7220 combo_links, dest_process, source_process,
7221 move
7222 ? "The combos used by the following bottle shops will be partially cleared by the move."
7223 : "The combos used by the following bottle shops will be partially or completely overwritten by this process."
7224 ));
7225 for(auto q = 0; q < 256; ++q)
7226 for(auto p = 0; p < 3; ++p)
7227 ADDC(&QMisc.bottle_shop_types[q].comb[p], fmt::format("{} slot {}", q, p));
7228
7229 if(!movelist->check_prot())
7230 return false;
7231 }
7232 //Screens //EXPENSIVE! DO THIS LAST!
7233 {
7234 auto& movelist = vec.emplace_back(std::make_unique<ComboMoveList>(
7235 combo_links, dest_process, source_process,
7236 move
7237 ? "The combos used by the following screens will be partially cleared by the move."
7238 : "The combos used by the following screens will be partially or completely overwritten by this process."
7239 ));
7240
7241 for(int32_t i=0; i<map_count && i<MAXMAPS; i++)
7242 {
7243 for(int32_t j=0; j<MAPSCRS; j++)
7244 {
7245 mapscr& scr = TheMaps[i*MAPSCRS+j];
7246
7247 if(!(scr.valid&mVALID))
7248 continue;
7249
7250 ADDC(&scr.undercombo, fmt::format("{}x{:02X} - UnderCombo", i, j));
7251
7252 // Specifying the exact position is too expensive - too much string creation.
7253 std::string data_str = ComboProtection ? fmt::format("{}x{:02X} - Combo", i, j) : "";
7254 for(int32_t k=0; k<176; k++)
7255 ADDC(&scr.data[k], data_str);
7256
7257 for(int32_t k=0; k<128; k++)
7258 ADDC(&scr.secretcombo[k], fmt::format("{}x{:02X} - SecretCombo {}", i, j, k));
7259
7260 word maxffc = scr.numFFC();
7261 for(word k=0; k<maxffc; k++)
7262 {
7263 ffcdata& ffc = scr.ffcs[k];
7264 ADDC(&ffc.data, fmt::format("{}x{:02X} - FFC {}", i, j, k+1));
7265 }
7266 }
7267 }
7268
7269 if(!movelist->check_prot())
7270 return false;
7271 }
7272 if(source_process) //Apply the 'diff' value to all moved combos
7273 storage.redo();
7274 return true;
7275 }
7276
7277 bool handle_combo_move(ComboMoveProcess dest_process)
7278 {
7279 return _handle_combo_move(dest_process, nullopt, 0, nullptr);
7280 }
7281 bool handle_combo_move(ComboMoveProcess dest_process, ComboMoveProcess source_process, int diff, ComboMoveUndo& on_undo)
7282 {
7283 return _handle_combo_move(dest_process, source_process, diff, &on_undo);
7284 }
7285 void register_used_tiles()
7286 {
7287 memset(used_tile_table, 0, sizeof(used_tile_table));
7288 for_every_used_tile([&](int tile)
7289 {
7290 used_tile_table[tile] = true;
7291 });
7292 }
7293
7294 bool overlay_tiles(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect_sel, bool move, int32_t cs, bool backwards)
7295 {
7296 bool ctrl=(CHECK_CTRL_CMD);
7297 bool copied=false;
7298 copied=overlay_tiles_united(tile,tile2,copy,copycnt,rect_sel,move,cs,backwards);
7299
7300 if(copied)
7301 {
7302 saved=false;
7303 }
7304
7305 return copied;
7306 }
7307
7308 bool overlay_tiles_united(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect, bool move, int32_t cs, bool backwards)
7309 {
7310 bool alt=(key[KEY_ALT]||key[KEY_ALTGR]);
7311 bool shift=(key[KEY_LSHIFT] || key[KEY_RSHIFT]);
7312
7313 // if tile>tile2 then swap them
7314 if(tile>tile2)
7315 {
7316 zc_swap(tile, tile2);
7317 }
7318
7319 // alt=copy from right
7320 // shift=copy from bottom
7321
7322 int32_t copies=copycnt;
7323 int32_t dest_first=tile;
7324 int32_t dest_last=tile2;
7325 int32_t src_first=copy;
7326 int32_t src_last=copy+copies-1;
7327
7328 int32_t dest_top=0;
7329 int32_t dest_bottom=0;
7330 int32_t src_top=0;
7331 int32_t src_bottom=0;
7332 int32_t src_left=0, src_right=0;
7333 int32_t src_width=0, src_height=0;
7334 int32_t dest_left=0, dest_right=0;
7335 int32_t dest_width=0, dest_height=0;
7336 int32_t rows=0, cols=0;
7337
7338 if(rect)
7339 {
7340 dest_top=TILEROW(dest_first);
7341 dest_bottom=TILEROW(dest_last);
7342 src_top=TILEROW(src_first);
7343 src_bottom=TILEROW(src_last);
7344
7345 src_left= zc_min(TILECOL(src_first),TILECOL(src_last));
7346 src_right=zc_max(TILECOL(src_first),TILECOL(src_last));
7347 src_first=(src_top * TILES_PER_ROW)+src_left;
7348 src_last= (src_bottom*TILES_PER_ROW)+src_right;
7349
7350 dest_left= zc_min(TILECOL(dest_first),TILECOL(dest_last));
7351 dest_right=zc_max(TILECOL(dest_first),TILECOL(dest_last));
7352 dest_first=(dest_top * TILES_PER_ROW)+dest_left;
7353 dest_last= (dest_bottom*TILES_PER_ROW)+dest_right;
7354
7355 //if no dest range set, then set one
7356 if((dest_first==dest_last)&&(src_first!=src_last))
7357 {
7358 if(alt)
7359 {
7360 dest_left=dest_right-(src_right-src_left);
7361 }
7362 else
7363 {
7364 dest_right=dest_left+(src_right-src_left);
7365 }
7366
7367 if(shift)
7368 {
7369 dest_top=dest_bottom-(src_bottom-src_top);
7370 }
7371 else
7372 {
7373 dest_bottom=dest_top+(src_bottom-src_top);
7374 }
7375
7376 dest_first=(dest_top * TILES_PER_ROW)+dest_left;
7377 dest_last= (dest_bottom*TILES_PER_ROW)+dest_right;
7378 }
7379 else
7380 {
7381 if(dest_right-dest_left<src_right-src_left) //destination is shorter than source
7382 {
7383 if(alt) //copy from right tile instead of left
7384 {
7385 src_left=src_right-(dest_right-dest_left);
7386 }
7387 else //copy from left tile
7388 {
7389 src_right=src_left+(dest_right-dest_left);
7390 }
7391 }
7392 else if(dest_right-dest_left>src_right-src_left) //destination is longer than source
7393 {
7394 if(alt) //copy from right tile instead of left
7395 {
7396 dest_left=dest_right-(src_right-src_left);
7397 }
7398 else //copy from left tile
7399 {
7400 dest_right=dest_left+(src_right-src_left);
7401 }
7402 }
7403
7404 if(dest_bottom-dest_top<src_bottom-src_top) //destination is shorter than source
7405 {
7406 if(shift) //copy from bottom tile instead of top
7407 {
7408 src_top=src_bottom-(dest_bottom-dest_top);
7409 }
7410 else //copy from top tile
7411 {
7412 src_bottom=src_top+(dest_bottom-dest_top);
7413 }
7414 }
7415 else if(dest_bottom-dest_top>src_bottom-src_top) //destination is longer than source
7416 {
7417 if(shift) //copy from bottom tile instead of top
7418 {
7419 dest_top=dest_bottom-(src_bottom-src_top);
7420 }
7421 else //copy from top tile
7422 {
7423 dest_bottom=dest_top+(src_bottom-src_top);
7424 }
7425 }
7426
7427 src_first=(src_top * TILES_PER_ROW)+src_left;
7428 src_last= (src_bottom*TILES_PER_ROW)+src_right;
7429 dest_first=(dest_top * TILES_PER_ROW)+dest_left;
7430 dest_last= (dest_bottom*TILES_PER_ROW)+dest_right;
7431 }
7432
7433 cols=src_right-src_left+1;
7434 rows=src_bottom-src_top+1;
7435
7436 dest_width=dest_right-dest_left+1;
7437 dest_height=dest_bottom-dest_top+1;
7438 src_width=src_right-src_left+1;
7439 src_height=src_bottom-src_top+1;
7440
7441 }
7442 else //!rect
7443 {
7444 //if no dest range set, then set one
7445 if((dest_first==dest_last)&&(src_first!=src_last))
7446 {
7447 if(alt)
7448 {
7449 dest_first=dest_last-(src_last-src_first);
7450 }
7451 else
7452 {
7453 dest_last=dest_first+(src_last-src_first);
7454 }
7455 }
7456 else
7457 {
7458 if(dest_last-dest_first<src_last-src_first) //destination is shorter than source
7459 {
7460 if(alt) //copy from last tile instead of first
7461 {
7462 src_first=src_last-(dest_last-dest_first);
7463 }
7464 else //copy from first tile
7465 {
7466 src_last=src_first+(dest_last-dest_first);
7467 }
7468 }
7469 else if(dest_last-dest_first>src_last-src_first) //destination is longer than source
7470 {
7471 if(alt) //copy from last tile instead of first
7472 {
7473 dest_first=dest_last-(src_last-src_first);
7474 }
7475 else //copy from first tile
7476 {
7477 dest_last=dest_first+(src_last-src_first);
7478 }
7479 }
7480 }
7481
7482 copies=dest_last-dest_first+1;
7483 }
7484
7485
7486
7487 char buf2[80], buf3[80], buf4[80];
7488 sprintf(buf2, " ");
7489 sprintf(buf3, " ");
7490 sprintf(buf4, " ");
7491
7492 // warn if range extends beyond last tile
7493 sprintf(buf4, "Some tiles will not be %s", move?"moved.":"copied.");
7494
7495 if(dest_last>=NEWMAXTILES)
7496 {
7497 sprintf(buf4, "%s operation cancelled.", move?"Move":"Copy");
7498 jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", NULL, 'o', 0, get_zc_font(font_lfont));
7499 return false;
7500 //fix this below to allow the operation to complete with a modified start or end instead of just cancelling
7501 //if (jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", "&Cancel", 'o', 'c', get_zc_font(font_lfont))==2)
7502 // {
7503 // return false;
7504 // }
7505 }
7506
7507
7508 TileMoveUndo on_undo;
7509 // Overwrite warnings
7510 TileMoveProcess dest{rect, dest_left, dest_top, dest_width, dest_height, dest_first, dest_last};
7511 if(move)
7512 {
7513 TileMoveProcess src{rect, src_left, src_top, src_width, src_height, src_first, src_last};
7514 if(!handle_tile_move(dest, src, dest_first-src_first, on_undo))
7515 return false;
7516 }
7517 else
7518 {
7519 if(!handle_tile_move(dest))
7520 return false;
7521 }
7522 // copy tiles and delete if needed (move)
7523
7524 {
7525 go_tiles();
7526
7527 int32_t diff=dest_first-src_first;
7528
7529 if(rect)
7530 {
7531 for(int32_t r=0; r<rows; ++r)
7532 {
7533 for(int32_t c=0; c<cols; ++c)
7534 {
7535 int32_t dt=(dest_first+((r*TILES_PER_ROW)+c));
7536 int32_t st=(src_first+((r*TILES_PER_ROW)+c));
7537
7538 if(dt>=NEWMAXTILES)
7539 continue;
7540
7541 overlay_tile(newtilebuf,dt,st,cs,backwards);
7542
7543 }
7544 }
7545 }
7546 else
7547 {
7548 for(int32_t c=0; c<copies; ++c)
7549 {
7550 int32_t dt=(dest_first+c);
7551 int32_t st=(src_first+c);
7552
7553 if(dt>=NEWMAXTILES)
7554 continue;
7555
7556 overlay_tile(newtilebuf,dt,st,cs,backwards);
7557
7558 if(move)
7559 {
7560 if(st<dest_first||st>(dest_first+c-1))
7561 reset_tile(newtilebuf, st, tf4Bit);
7562 }
7563 }
7564 }
7565 }
7566
7567 //now that tiles have moved, fix these buffers -DD
7568 register_blank_tiles();
7569 register_used_tiles();
7570
7571 if(move)
7572 last_tile_move_list = std::move(on_undo);
7573 return true;
7574 }
7575 //
7576 bool do_movetile_united(tile_move_data const& tmd)
7577 {
7578 char buf2[80], buf3[80], buf4[80];
7579 sprintf(buf2, " ");
7580 sprintf(buf3, " ");
7581 sprintf(buf4, " ");
7582
7583 // warn if range extends beyond last tile
7584 sprintf(buf4, "Some tiles will not be %s", tmd.move?"moved.":"copied.");
7585
7586 if(tmd.dest_last>=NEWMAXTILES)
7587 {
7588 sprintf(buf4, "%s operation cancelled.", tmd.move?"Move":"Copy");
7589 jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", NULL, 'o', 0, get_zc_font(font_lfont));
7590 return false;
7591 }
7592
7593 TileMoveUndo on_undo;
7594 // Overwrite warnings
7595 TileMoveProcess dest{tmd.rect, tmd.dest_left, tmd.dest_top, tmd.dest_width, tmd.dest_height, tmd.dest_first, tmd.dest_last};
7596 if(tmd.move)
7597 {
7598 TileMoveProcess src{tmd.rect, tmd.src_left, tmd.src_top, tmd.src_width, tmd.src_height, tmd.src_first, tmd.src_last};
7599 if(!handle_tile_move(dest, src, tmd.dest_first-tmd.src_first, on_undo))
7600 return false;
7601 }
7602 else
7603 {
7604 if(!handle_tile_move(dest))
7605 return false;
7606 }
7607
7608 // copy tiles and delete if needed (tmd.move)
7609 {
7610 go_tiles();
7611
7612 if(tmd.rect)
7613 {
7614 for(int32_t r=0; r<tmd.rows; ++r)
7615 {
7616 for(int32_t c=0; c<tmd.cols; ++c)
7617 {
7618 int32_t dt=(tmd.dest_first+((r*TILES_PER_ROW)+c));
7619 int32_t st=(tmd.src_first+((r*TILES_PER_ROW)+c));
7620
7621 if(dt>=NEWMAXTILES)
7622 continue;
7623
7624 reset_tile(newtilebuf, dt, newundotilebuf[st].format);
7625
7626 for(int32_t j=0; j<tilesize(newundotilebuf[st].format); j++)
7627 {
7628 newtilebuf[dt].data[j]=newundotilebuf[st].data[j];
7629 }
7630
7631 if(tmd.move)
7632 {
7633 if((st<tmd.dest_first||st>tmd.dest_first+((tmd.rows-1)*TILES_PER_ROW)+(tmd.cols-1)))
7634 reset_tile(newtilebuf, st, tf4Bit);
7635 else
7636 {
7637 int32_t destLeft=tmd.dest_first%TILES_PER_ROW;
7638 int32_t destRight=(tmd.dest_first+tmd.cols-1)%TILES_PER_ROW;
7639 if(destLeft<=destRight)
7640 {
7641 if(st%TILES_PER_ROW<destLeft || st%TILES_PER_ROW>destRight)
7642 reset_tile(newtilebuf, st, tf4Bit);
7643 }
7644 else // Wrapped around
7645 {
7646 if(st%TILES_PER_ROW<destLeft && st%TILES_PER_ROW>destRight)
7647 reset_tile(newtilebuf, st, tf4Bit);
7648 }
7649 }
7650 }
7651 }
7652 }
7653 }
7654 else
7655 {
7656 for(int32_t c=0; c<tmd.copies; ++c)
7657 {
7658 int32_t dt=(tmd.dest_first+c);
7659 int32_t st=(tmd.src_first+c);
7660
7661 if(dt>=NEWMAXTILES)
7662 continue;
7663
7664 reset_tile(newtilebuf, dt, newundotilebuf[st].format);
7665
7666 for(int32_t j=0; j<tilesize(newundotilebuf[st].format); j++)
7667 {
7668 newtilebuf[dt].data[j]=newundotilebuf[st].data[j];
7669 }
7670
7671 if(tmd.move)
7672 {
7673 if(st<tmd.dest_first||st>(tmd.dest_first+c-1))
7674 reset_tile(newtilebuf, st, tf4Bit);
7675 }
7676 }
7677 }
7678 }
7679
7680 //now that tiles have moved, fix these buffers -DD
7681 register_blank_tiles();
7682 register_used_tiles();
7683
7684 if(tmd.move)
7685 last_tile_move_list = std::move(on_undo);
7686 return true;
7687 }
7688
7689 bool copy_tiles_united(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect, bool move)
7690 {
7691 bool alt=(key[KEY_ALT]||key[KEY_ALTGR]);
7692 bool shift=(key[KEY_LSHIFT] || key[KEY_RSHIFT]);
7693
7694 // if tile>tile2 then swap them
7695 if(tile>tile2)
7696 {
7697 zc_swap(tile, tile2);
7698 }
7699
7700 // alt=copy from right
7701 // shift=copy from bottom
7702 tile_move_data tmd;
7703
7704 tmd.copies=copycnt;
7705 tmd.dest_first=tile;
7706 tmd.dest_last=tile2;
7707 tmd.src_first=copy;
7708 tmd.src_last=copy+tmd.copies-1;
7709 tmd.rect = rect;
7710 tmd.move = move;
7711
7712 if(rect)
7713 {
7714 tmd.dest_top=TILEROW(tmd.dest_first);
7715 tmd.dest_bottom=TILEROW(tmd.dest_last);
7716 tmd.src_top=TILEROW(tmd.src_first);
7717 tmd.src_bottom=TILEROW(tmd.src_last);
7718
7719 tmd.src_left= zc_min(TILECOL(tmd.src_first),TILECOL(tmd.src_last));
7720 tmd.src_right=zc_max(TILECOL(tmd.src_first),TILECOL(tmd.src_last));
7721 tmd.src_first=(tmd.src_top * TILES_PER_ROW)+tmd.src_left;
7722 tmd.src_last= (tmd.src_bottom*TILES_PER_ROW)+tmd.src_right;
7723
7724 tmd.dest_left= zc_min(TILECOL(tmd.dest_first),TILECOL(tmd.dest_last));
7725 tmd.dest_right=zc_max(TILECOL(tmd.dest_first),TILECOL(tmd.dest_last));
7726 tmd.dest_first=(tmd.dest_top * TILES_PER_ROW)+tmd.dest_left;
7727 tmd.dest_last= (tmd.dest_bottom*TILES_PER_ROW)+tmd.dest_right;
7728
7729 //if no dest range set, then set one
7730 if((tmd.dest_first==tmd.dest_last)&&(tmd.src_first!=tmd.src_last))
7731 {
7732 if(alt)
7733 {
7734 tmd.dest_left=tmd.dest_right-(tmd.src_right-tmd.src_left);
7735 }
7736 else
7737 {
7738 tmd.dest_right=tmd.dest_left+(tmd.src_right-tmd.src_left);
7739 }
7740
7741 if(shift)
7742 {
7743 tmd.dest_top=tmd.dest_bottom-(tmd.src_bottom-tmd.src_top);
7744 }
7745 else
7746 {
7747 tmd.dest_bottom=tmd.dest_top+(tmd.src_bottom-tmd.src_top);
7748 }
7749
7750 tmd.dest_first=(tmd.dest_top * TILES_PER_ROW)+tmd.dest_left;
7751 tmd.dest_last= (tmd.dest_bottom*TILES_PER_ROW)+tmd.dest_right;
7752 }
7753 else
7754 {
7755 if(tmd.dest_right-tmd.dest_left<tmd.src_right-tmd.src_left) //destination is shorter than source
7756 {
7757 if(alt) //copy from right tile instead of left
7758 {
7759 tmd.src_left=tmd.src_right-(tmd.dest_right-tmd.dest_left);
7760 }
7761 else //copy from left tile
7762 {
7763 tmd.src_right=tmd.src_left+(tmd.dest_right-tmd.dest_left);
7764 }
7765 }
7766 else if(tmd.dest_right-tmd.dest_left>tmd.src_right-tmd.src_left) //destination is longer than source
7767 {
7768 if(alt) //copy from right tile instead of left
7769 {
7770 tmd.dest_left=tmd.dest_right-(tmd.src_right-tmd.src_left);
7771 }
7772 else //copy from left tile
7773 {
7774 tmd.dest_right=tmd.dest_left+(tmd.src_right-tmd.src_left);
7775 }
7776 }
7777
7778 if(tmd.dest_bottom-tmd.dest_top<tmd.src_bottom-tmd.src_top) //destination is shorter than source
7779 {
7780 if(shift) //copy from bottom tile instead of top
7781 {
7782 tmd.src_top=tmd.src_bottom-(tmd.dest_bottom-tmd.dest_top);
7783 }
7784 else //copy from top tile
7785 {
7786 tmd.src_bottom=tmd.src_top+(tmd.dest_bottom-tmd.dest_top);
7787 }
7788 }
7789 else if(tmd.dest_bottom-tmd.dest_top>tmd.src_bottom-tmd.src_top) //destination is longer than source
7790 {
7791 if(shift) //copy from bottom tile instead of top
7792 {
7793 tmd.dest_top=tmd.dest_bottom-(tmd.src_bottom-tmd.src_top);
7794 }
7795 else //copy from top tile
7796 {
7797 tmd.dest_bottom=tmd.dest_top+(tmd.src_bottom-tmd.src_top);
7798 }
7799 }
7800
7801 tmd.src_first=(tmd.src_top * TILES_PER_ROW)+tmd.src_left;
7802 tmd.src_last= (tmd.src_bottom*TILES_PER_ROW)+tmd.src_right;
7803 tmd.dest_first=(tmd.dest_top * TILES_PER_ROW)+tmd.dest_left;
7804 tmd.dest_last= (tmd.dest_bottom*TILES_PER_ROW)+tmd.dest_right;
7805 }
7806
7807 tmd.cols=tmd.src_right-tmd.src_left+1;
7808 tmd.rows=tmd.src_bottom-tmd.src_top+1;
7809
7810 tmd.dest_width=tmd.dest_right-tmd.dest_left+1;
7811 tmd.dest_height=tmd.dest_bottom-tmd.dest_top+1;
7812 tmd.src_width=tmd.src_right-tmd.src_left+1;
7813 tmd.src_height=tmd.src_bottom-tmd.src_top+1;
7814
7815 }
7816 else //!rect
7817 {
7818 //if no dest range set, then set one
7819 if((tmd.dest_first==tmd.dest_last)&&(tmd.src_first!=tmd.src_last))
7820 {
7821 if(alt)
7822 {
7823 tmd.dest_first=tmd.dest_last-(tmd.src_last-tmd.src_first);
7824 }
7825 else
7826 {
7827 tmd.dest_last=tmd.dest_first+(tmd.src_last-tmd.src_first);
7828 }
7829 }
7830 else
7831 {
7832 if(tmd.dest_last-tmd.dest_first<tmd.src_last-tmd.src_first) //destination is shorter than source
7833 {
7834 if(alt) //copy from last tile instead of first
7835 {
7836 tmd.src_first=tmd.src_last-(tmd.dest_last-tmd.dest_first);
7837 }
7838 else //copy from first tile
7839 {
7840 tmd.src_last=tmd.src_first+(tmd.dest_last-tmd.dest_first);
7841 }
7842 }
7843 else if(tmd.dest_last-tmd.dest_first>tmd.src_last-tmd.src_first) //destination is longer than source
7844 {
7845 if(alt) //copy from last tile instead of first
7846 {
7847 tmd.dest_first=tmd.dest_last-(tmd.src_last-tmd.src_first);
7848 }
7849 else //copy from first tile
7850 {
7851 tmd.dest_last=tmd.dest_first+(tmd.src_last-tmd.src_first);
7852 }
7853 }
7854 }
7855
7856 tmd.copies=tmd.dest_last-tmd.dest_first+1;
7857 }
7858
7859 return do_movetile_united(tmd);
7860 }
7861
7862 //
7863
7864 bool copy_tiles_united_floodfill(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect, bool move)
7865 {
7866 assert(!move); //not implemented
7867
7868 // if tile>tile2 then swap them
7869 if(tile>tile2)
7870 {
7871 zc_swap(tile, tile2);
7872 }
7873
7874 tile_move_data tmd;
7875 tmd.copies=copycnt;
7876 tmd.dest_first=tile;
7877 tmd.dest_last=tile2;
7878 tmd.src_first=copy;
7879 tmd.src_last=copy+tmd.copies-1;
7880
7881
7882
7883 if(rect)
7884 {
7885 tmd.dest_top=TILEROW(tmd.dest_first);
7886 tmd.dest_bottom=TILEROW(tmd.dest_last);
7887 //tmd.src_top=TILEROW(tmd.src_first);
7888 //tmd.src_bottom=TILEROW(tmd.src_last);
7889
7890 //tmd.src_left= zc_min(TILECOL(tmd.src_first),TILECOL(tmd.src_last));
7891 //tmd.src_right=zc_max(TILECOL(tmd.src_first),TILECOL(tmd.src_last));
7892 //tmd.src_first=(tmd.src_top * TILES_PER_ROW)+tmd.src_left;
7893 //tmd.src_last= (tmd.src_bottom*TILES_PER_ROW)+tmd.src_right;
7894
7895 tmd.dest_left= zc_min(TILECOL(tmd.dest_first),TILECOL(tmd.dest_last));
7896 tmd.dest_right=zc_max(TILECOL(tmd.dest_first),TILECOL(tmd.dest_last));
7897 tmd.dest_first=(tmd.dest_top * TILES_PER_ROW)+tmd.dest_left;
7898 tmd.dest_last= (tmd.dest_bottom*TILES_PER_ROW)+tmd.dest_right;
7899
7900
7901
7902
7903 tmd.dest_width=tmd.dest_right-tmd.dest_left;
7904 tmd.dest_height=tmd.dest_bottom-tmd.dest_top;
7905
7906 tmd.cols=tmd.dest_width+1;
7907 tmd.rows=tmd.dest_height+1;
7908
7909 al_trace("tmd.rows: %d\n", tmd.rows);
7910 al_trace("tmd.cols: %d\n", tmd.cols);
7911
7912
7913 }
7914 else //!rect
7915 {
7916 tmd.copies=tmd.dest_last-tmd.dest_first+1;
7917 }
7918
7919
7920
7921 char buf2[80], buf3[80], buf4[80];
7922 sprintf(buf2, " ");
7923 sprintf(buf3, " ");
7924 sprintf(buf4, " ");
7925
7926 // warn if range extends beyond last tile
7927 sprintf(buf4, "Some tiles will not be %s", move?"moved.":"copied.");
7928
7929 if(tmd.dest_last>=NEWMAXTILES)
7930 {
7931 sprintf(buf4, "%s operation cancelled.", move?"Move":"Copy");
7932 jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", NULL, 'o', 0, get_zc_font(font_lfont));
7933 return false;
7934 //fix this below to allow the operation to complete with a modified start or end instead of just cancelling
7935 //if (jwin_alert("Destination Error", "The destination extends beyond", "the last available tile row.", buf4, "&OK", "&Cancel", 'o', 'c', get_zc_font(font_lfont))==2)
7936 // {
7937 // return false;
7938 // }
7939 }
7940
7941 TileMoveUndo on_undo;
7942 // Overwrite warnings
7943 TileMoveProcess dest{tmd.rect, tmd.dest_left, tmd.dest_top, tmd.dest_width, tmd.dest_height, tmd.dest_first, tmd.dest_last};
7944 if(tmd.move)
7945 {
7946 TileMoveProcess src{tmd.rect, tmd.src_left, tmd.src_top, tmd.src_width, tmd.src_height, tmd.src_first, tmd.src_last};
7947 if(!handle_tile_move(dest, src, tmd.dest_first-tmd.src_first, on_undo))
7948 return false;
7949 }
7950 else
7951 {
7952 if(!handle_tile_move(dest))
7953 return false;
7954 }
7955
7956 // copy tiles and delete if needed (move)
7957
7958 {
7959 go_tiles();
7960
7961 int32_t diff=tmd.dest_first-tmd.src_first;
7962
7963 if(rect)
7964 {
7965 al_trace("floodfill, rect\n");
7966 al_trace("tmd.rows: %d\n", tmd.rows);
7967 al_trace("tmd.cols: %d\n", tmd.cols);
7968 for(int32_t r=0; r<tmd.rows; ++r)
7969 {
7970 for(int32_t c=0; c<tmd.cols; ++c)
7971 {
7972 int32_t dt=(tmd.dest_first+((r*TILES_PER_ROW)+c));
7973 //int32_t st=(tmd.src_first+((r*TILES_PER_ROW)+c));
7974
7975 if(dt>=NEWMAXTILES)
7976 continue;
7977
7978 reset_tile(newtilebuf, dt, newundotilebuf[copy].format);
7979
7980 for(int32_t j=0; j<tilesize(newundotilebuf[copy].format); j++)
7981 {
7982 newtilebuf[dt].data[j]=newundotilebuf[copy].data[j];
7983 }
7984 }
7985 }
7986 }
7987 else
7988 {
7989 for(int32_t c=0; c<tmd.copies; ++c)
7990 {
7991 int32_t dt=(tmd.dest_first+c);
7992 int32_t st=(tmd.src_first+c);
7993
7994 if(dt>=NEWMAXTILES)
7995 continue;
7996
7997 reset_tile(newtilebuf, dt, newundotilebuf[copy].format);
7998
7999 for(int32_t j=0; j<tilesize(newundotilebuf[copy].format); j++)
8000 {
8001 newtilebuf[dt].data[j]=newundotilebuf[copy].data[j];
8002 }
8003
8004 }
8005 }
8006 }
8007
8008 //now that tiles have moved, fix these buffers -DD
8009 register_blank_tiles();
8010 register_used_tiles();
8011
8012 if(tmd.move)
8013 last_tile_move_list = std::move(on_undo);
8014 return true;
8015 }
8016 //
8017
8018 bool copy_tiles_floodfill(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect_sel, bool move)
8019 {
8020 al_trace("Floodfill Psste\n");
8021 bool ctrl=(CHECK_CTRL_CMD);
8022 bool copied=false;
8023 copied=copy_tiles_united_floodfill(tile,tile2,copy,copycnt,rect_sel,move);
8024
8025 if(copied)
8026 {
8027 if(!ctrl)
8028 {
8029 copy=-1;
8030 tile2=tile;
8031 }
8032
8033 saved=false;
8034 }
8035
8036 return copied;
8037 }
8038
8039 bool copy_tiles(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool rect_sel, bool move)
8040 {
8041 bool ctrl=(CHECK_CTRL_CMD);
8042 bool copied=false;
8043 copied=copy_tiles_united(tile,tile2,copy,copycnt,rect_sel,move);
8044
8045 if(copied)
8046 {
8047 if(!ctrl)
8048 {
8049 copy=-1;
8050 tile2=tile;
8051 }
8052
8053 saved=false;
8054 }
8055
8056 return copied;
8057 }
8058
8059 bool scale_or_rotate_tiles(int32_t &tile, int32_t &tile2, int32_t &cs, bool rotate)
8060 {
8061 // if tile>tile2 then swap them
8062 if(tile>tile2)
8063 {
8064 zc_swap(tile, tile2);
8065 }
8066 int32_t src_top = TILEROW(tile);
8067 int32_t src_bottom = TILEROW(tile2);
8068 int32_t src_left = zc_min(TILECOL(tile),TILECOL(tile2));
8069 int32_t src_right = zc_max(TILECOL(tile),TILECOL(tile2));
8070 int32_t src_first = (src_top * TILES_PER_ROW)+src_left;
8071 int32_t src_last = (src_bottom*TILES_PER_ROW)+src_right;
8072
8073 int32_t src_width = src_right-src_left+1,
8074 src_height = src_bottom-src_top+1;
8075 int32_t dest_width = src_width, dest_height = src_height;
8076 zfix dest_rot = 0_zf;
8077 if(rotate)
8078 RotateTileDialog(&dest_width, &dest_height, &dest_rot).show();
8079 else
8080 ScaleTileDialog(&dest_width, &dest_height).show();
8081 if (rotate)
8082 {
8083 if (dest_rot == 0) return false;
8084 }
8085 else
8086 {
8087 if (dest_width == src_width && dest_height == src_height) return false; //no scaling
8088 }
8089 dest_width = vbound(dest_width, 1, 20);
8090 dest_height = vbound(dest_height, 1, 20);
8091
8092 int32_t dest_top = src_top;
8093 int32_t dest_bottom = src_top+dest_height-1;
8094 int32_t dest_left = src_left;
8095 int32_t dest_right = src_left+dest_width-1;
8096 int32_t dest_first = src_first;
8097 int32_t dest_last = (dest_bottom*TILES_PER_ROW)+dest_right;
8098
8099
8100 if(dest_last>=NEWMAXTILES)
8101 {
8102 InfoDialog("Destination Error", "The destination extends beyond the last available tile row. Scale operation cancelled.").show();
8103 return false;
8104 }
8105
8106 // Overwrite warnings
8107 if(!handle_tile_move({true, dest_left, dest_top, dest_width, dest_height, dest_first, dest_last}))
8108 return false;
8109
8110 //Do the rotate
8111 {
8112 go_tiles();
8113
8114 int32_t diff=dest_first-src_first;
8115 BITMAP *srcbmp = create_bitmap_ex(8,src_width*16,src_height*16),
8116 *destbmp = create_bitmap_ex(8,dest_width*16,dest_height*16);
8117 clear_bitmap(srcbmp); clear_bitmap(destbmp);
8118 overtileblock16(srcbmp, src_first, 0, 0, src_width, src_height, cs, 0);
8119 bool is8bit = newtilebuf[src_first].format == tf8Bit;
8120 if (rotate)
8121 {
8122 rotate_sprite(destbmp, srcbmp, 0, 0, ftofix(dest_rot * 0.7111111111111));
8123 }
8124 else
8125 {
8126 stretch_blit(srcbmp, destbmp, 0, 0, srcbmp->w, srcbmp->h,
8127 0, 0, destbmp->w, destbmp->h);
8128 }
8129 int32_t mhei = zc_max(src_height,dest_height),
8130 mwid = zc_max(src_width, dest_width);
8131 for(int32_t r=0; r<mhei; ++r)
8132 {
8133 for(int32_t c=0; c<mwid; ++c)
8134 {
8135 int32_t dt=(dest_first+((r*TILES_PER_ROW)+c));
8136
8137 if(dt>=NEWMAXTILES)
8138 continue;
8139 if(r < dest_height && c < dest_width)
8140 {
8141 write_tile(newtilebuf, destbmp, dt, c*16, r*16, is8bit, false);
8142 }
8143 else reset_tile(newtilebuf, dt, tf4Bit);
8144 }
8145 }
8146 }
8147
8148 register_blank_tiles();
8149 register_used_tiles();
8150 return true;
8151 }
8152
8153 void copy_combos(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt, bool masscopy)
8154 {
8155 //these 2 shouldn't be needed, but just to be safe...
8156 reset_combo_animations();
8157 reset_combo_animations2();
8158
8159 if(tile2<tile)
8160 {
8161 zc_swap(tile,tile2);
8162 }
8163
8164 auto first = tile;
8165 auto last = masscopy ? tile2 : first + copycnt-1;
8166 if(!handle_combo_move({first,last}))
8167 return;
8168
8169 if(!masscopy)
8170 {
8171 if(tile==copy)
8172 {
8173 copy=-1;
8174 tile2=tile;
8175 return;
8176 }
8177
8178 // go_combos(); // commented because caller does it for us
8179 //if copying to an earlier combo, copy from left to right
8180 //otherwise, copy from right to left
8181 for(int32_t t=(tile<copy)?0:(copycnt-1); (tile<copy)?(t<copycnt):(t>=0); (tile<copy)?(t++):(t--))
8182 {
8183 if(tile+t < MAXCOMBOS)
8184 {
8185 combobuf[tile+t]=combobuf[copy+t];
8186 }
8187 }
8188
8189 copy=-1;
8190 tile2=tile;
8191 saved=false;
8192 }
8193 else
8194 {
8195 // go_combos();
8196 int32_t src=copy, dest=tile;
8197
8198 do
8199 {
8200 combobuf[dest]=combobuf[src];
8201 ++src;
8202 ++dest;
8203
8204 if((src-copy)==copycnt) src=copy;
8205 }
8206 while(dest<=tile2);
8207
8208 copy=-1;
8209 tile2=tile;
8210 saved=false;
8211 }
8212
8213 setup_combo_animations();
8214 setup_combo_animations2();
8215 }
8216
8217 bool do_movecombo(combo_move_data const& cmd, ComboMoveUndo& on_undo, bool is_undoing)
8218 {
8219 reset_combo_animations();
8220 reset_combo_animations2();
8221 go_combos();
8222
8223 auto diff = cmd.tile - cmd.copy1;
8224 if(is_undoing)
8225 on_undo.undo();
8226 else if(!handle_combo_move({cmd.tile,cmd.tile+cmd.copycnt-1},{cmd.copy1,cmd.copy1+cmd.copycnt-1}, diff, on_undo))
8227 return false;
8228
8229 for(int32_t t=(cmd.tile<cmd.copy1)?0:(cmd.copycnt-1); (cmd.tile<cmd.copy1)?(t<cmd.copycnt):(t>=0); (cmd.tile<cmd.copy1)?(t++):(t--))
8230 {
8231 if(cmd.tile+t < MAXCOMBOS)
8232 {
8233 combobuf[cmd.tile+t]=combobuf[cmd.copy1+t];
8234 clear_combo(cmd.copy1+t);
8235 }
8236 }
8237
8238 setup_combo_animations();
8239 setup_combo_animations2();
8240 saved=false;
8241 return true;
8242 }
8243
8244 void move_combos(int32_t &tile,int32_t &tile2,int32_t &copy,int32_t &copycnt)
8245 {
8246 if(tile2<tile)
8247 {
8248 zc_swap(tile,tile2);
8249 }
8250
8251 if(tile==copy)
8252 {
8253 copy=-1;
8254 tile2=tile;
8255 return;
8256 }
8257
8258 combo_move_data cmd;
8259 cmd.tile = tile;
8260 cmd.tile2 = tile2;
8261 cmd.copy1 = copy;
8262 cmd.copycnt = copycnt;
8263
8264 ComboMoveUndo on_undo;
8265 if(!do_movecombo(cmd, on_undo))
8266 return;
8267 last_combo_move_list = std::move(on_undo);
8268 copy=-1;
8269 tile2=tile;
8270 }
8271
8272 void do_delete_tiles(int32_t firsttile, int32_t lasttile, bool rect_sel)
8273 {
8274 if(firsttile > lasttile)
8275 zc_swap(firsttile,lasttile);
8276 int32_t coldiff = 0;
8277 if(rect_sel && TILECOL(firsttile)>TILECOL(lasttile))
8278 {
8279 coldiff=TILECOL(firsttile)-TILECOL(lasttile);
8280 firsttile-=coldiff;
8281 lasttile+=coldiff;
8282 }
8283 for(int32_t t=firsttile; t<=lasttile; ++t)
8284 if(!rect_sel ||
8285 ((TILECOL(t)>=TILECOL(firsttile)) &&
8286 (TILECOL(t)<=TILECOL(lasttile))))
8287 reset_tile(newtilebuf, t, tf4Bit);
8288 saved=false;
8289 register_blank_tiles();
8290 }
8291
8292 void delete_tiles(int32_t &tile,int32_t &tile2,bool rect_sel)
8293 {
8294 char buf[40];
8295
8296 if(tile==tile2)
8297 {
8298 sprintf(buf,"Delete tile %d?",tile);
8299 }
8300 else
8301 {
8302 sprintf(buf,"Delete tiles %d-%d?",zc_min(tile,tile2),zc_max(tile,tile2));
8303 }
8304
8305 if(jwin_alert("Confirm Delete",buf,NULL,NULL,"&Yes","&No",'y','n',get_zc_font(font_lfont))==1)
8306 {
8307 int32_t firsttile=zc_min(tile,tile2), lasttile=zc_max(tile,tile2), coldiff=0;
8308
8309 go_tiles();
8310
8311 //if copying to an earlier tile, copy from left to right
8312 //otherwise, copy from right to left
8313 do_delete_tiles(firsttile, lasttile, rect_sel);
8314
8315 tile=tile2=zc_min(tile,tile2);
8316 saved=false;
8317 register_blank_tiles();
8318 }
8319 }
8320
8321 void overlay_tile2(int32_t dest,int32_t src,int32_t cs,bool backwards)
8322 {
8323 byte buf[256];
8324 go_tiles();
8325
8326 unpack_tile(newtilebuf, dest, 0, false);
8327
8328 for(int32_t i=0; i<256; i++)
8329 buf[i] = unpackbuf[i];
8330
8331 unpack_tile(newtilebuf, src, 0, false);
8332
8333 if(newtilebuf[src].format>tf4Bit)
8334 {
8335 cs=0;
8336 }
8337
8338 cs &= 15;
8339 cs <<= CSET_SHFT;
8340
8341 for(int32_t i=0; i<256; i++)
8342 {
8343 if(backwards)
8344 {
8345 if(!buf[i])
8346 {
8347 buf[i] = unpackbuf[i]+cs;
8348 }
8349 }
8350 else
8351 {
8352 if(unpackbuf[i])
8353 {
8354 buf[i] = unpackbuf[i]+cs;
8355 }
8356 }
8357 }
8358
8359 pack_tile(newtilebuf, buf,dest);
8360 saved=false;
8361 }
8362
8363 void mass_overlay_tile(int32_t dest1, int32_t dest2, int32_t src, int32_t cs, bool backwards, bool rect_sel)
8364 {
8365 //byte buf[256];
8366 go_tiles();
8367
8368 if(!rect_sel)
8369 {
8370 for(int32_t d=dest1; d <= dest2; ++d)
8371 {
8372 /*unpack_tile(newtilebuf, d, 0, false);
8373
8374 for(int32_t i=0; i<256; i++)
8375 {
8376 if(!backwards)
8377 {
8378 if(!buf[i])
8379 {
8380 buf[i] = unpackbuf[i] + cs;
8381 }
8382 }
8383 else
8384 {
8385 if(unpackbuf[i])
8386 {
8387 buf[i] = unpackbuf[i] + cs;
8388 }
8389 }
8390 }
8391
8392 pack_tile(newtilebuf, buf,d);
8393 */
8394
8395 overlay_tile(newtilebuf,d,src,cs,backwards);
8396
8397 if(!blank_tile_table[src])
8398 {
8399 blank_tile_table[d]=false;
8400 }
8401 }
8402 }
8403 else
8404 {
8405 int32_t rmin=zc_min(TILEROW(dest1),TILEROW(dest2));
8406 int32_t rmax=zc_max(TILEROW(dest1),TILEROW(dest2));
8407 int32_t cmin=zc_min(TILECOL(dest1),TILECOL(dest2));
8408 int32_t cmax=zc_max(TILECOL(dest1),TILECOL(dest2));
8409 int32_t d=0;
8410
8411 for(int32_t j=cmin; j<=cmax; ++j)
8412 {
8413 for(int32_t k=rmin; k<=rmax; ++k)
8414 {
8415 d=j+TILES_PER_ROW*k;
8416 /*unpack_tile(newtilebuf, d, 0, false);
8417
8418 for(int32_t i=0; i<256; i++)
8419 {
8420 if(!backwards)
8421 {
8422 if(!buf[i])
8423 {
8424 buf[i] = unpackbuf[i] + cs;
8425 }
8426 }
8427 else
8428 {
8429 if(unpackbuf[i])
8430 {
8431 buf[i] = unpackbuf[i] + cs;
8432 }
8433 }
8434 }
8435
8436 pack_tile(newtilebuf, buf,d);
8437 */
8438
8439 overlay_tile(newtilebuf,d,src,cs,backwards);
8440
8441 if(!blank_tile_table[src])
8442 {
8443 blank_tile_table[d]=false;
8444 }
8445 }
8446 }
8447 }
8448
8449 return;
8450 }
8451
8452 void sel_tile(int32_t &tile, int32_t &tile2, int32_t &first, int32_t type, int32_t s)
8453 {
8454 tile+=s;
8455 bound(tile,0,NEWMAXTILES-1);
8456
8457 if(type!=0 || !(key[KEY_LSHIFT] || key[KEY_RSHIFT]))
8458 tile2 = tile;
8459
8460 first = tile - (tile%TILES_PER_PAGE);
8461 }
8462
8463 void convert_tile(int32_t t, int32_t bp2, int32_t cs, bool shift, bool alt)
8464 {
8465 int32_t cst;
8466
8467 switch(bp2)
8468 {
8469 case tf4Bit:
8470 switch(newtilebuf[t].format)
8471 {
8472 case tf4Bit:
8473 //already in the right format
8474 break;
8475
8476 case tf8Bit:
8477 unpack_tile(newtilebuf, t, 0, true);
8478
8479 if(alt) //reduce
8480 {
8481 for(int32_t i=0; i<256; i++)
8482 {
8483 if(!shift||unpackbuf[i]!=0)
8484 {
8485 unpackbuf[i]=(cset_reduce_table[unpackbuf[i]]);
8486 }
8487 }
8488 }
8489 else //truncate
8490 {
8491 for(int32_t i=0; i<256; i++)
8492 {
8493 unpackbuf[i]&=15;
8494 }
8495 }
8496
8497 reset_tile(newtilebuf, t, tf4Bit);
8498 pack_tile(newtilebuf, unpackbuf, t);
8499 break;
8500 }
8501
8502 break;
8503
8504 case tf8Bit:
8505 switch(newtilebuf[t].format)
8506 {
8507 case tf4Bit:
8508 unpack_tile(newtilebuf, t, 0, true);
8509 cst = cs&15;
8510 cst <<= CSET_SHFT;
8511
8512 for(int32_t i=0; i<256; i++)
8513 {
8514 if(!shift||unpackbuf[i]!=0)
8515 {
8516 unpackbuf[i]+=cst;
8517 }
8518 }
8519
8520 reset_tile(newtilebuf, t, tf8Bit);
8521 pack_tile(newtilebuf, unpackbuf, t);
8522 break;
8523
8524 case tf8Bit:
8525 //already in the right format
8526 break;
8527 }
8528
8529 break;
8530 }
8531 }
8532
8533 static DIALOG create_relational_tiles_dlg[] =
8534 {
8535 // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp)
8536 9 { jwin_win_proc, 0, 0, 160, 92, vc(0), vc(11), 0, D_EXIT, 0, 0, (void *) "Tile Setup", NULL, NULL },
8537 9 { jwin_rtext_proc, 74, 28, 48, 8, jwin_pal[jcBOXFG], jwin_pal[jcBOX], 0, 0, 0, 0, (void *) "Frames:", NULL, NULL },
8538 9 { jwin_edit_proc, 78, 24, 48, 16, 0, 0, 0, 0, 6, 0, NULL, NULL, NULL },
8539 9 { jwin_radio_proc, 8, 44, 64, 9, vc(14), vc(1), 0, D_SELECTED, 0, 0, (void *) "Relational", NULL, NULL },
8540 9 { jwin_radio_proc, 68, 44, 64, 9, vc(14), vc(1), 0, 0, 0, 0, (void *) "Dungeon Carving", NULL, NULL },
8541 9 { jwin_button_proc, 10, 66, 61, 21, vc(0), vc(11), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
8542 9 { jwin_button_proc, 90, 66, 61, 21, vc(0), vc(11), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
8543 9 { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
8544 9 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
8545 };
8546
8547 void draw_tile_list_window()
8548 {
8549 int32_t w = 640;
8550 int32_t h = 480;
8551
8552 int32_t window_xofs=(zq_screen_w-w-12)>>1;
8553 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
8554 jwin_draw_win(screen, window_xofs, window_yofs, w+6+6, h+25+6, FR_WIN);
8555 jwin_draw_frame(screen, window_xofs+4, window_yofs+23, w+2+2, h+4+2-64, FR_DEEP);
8556
8557 FONT *oldfont = font;
8558 font = get_zc_font(font_lfont);
8559 jwin_draw_titlebar(screen, window_xofs+3, window_yofs+3, w+6, 18, "Select Tile", true);
8560 font=oldfont;
8561 return;
8562 }
8563
8564 void show_blank_tile(int32_t t)
8565 {
8566 char tbuf[80], tbuf2[80], tbuf3[80];
8567 sprintf(tbuf, "Tile is%s blank.", blank_tile_table[t]?"":" not");
8568 sprintf(tbuf2, "%c %c", blank_tile_quarters_table[t*4]?'X':'-', blank_tile_quarters_table[(t*4)+1]?'X':'-');
8569 sprintf(tbuf3, "%c %c", blank_tile_quarters_table[(t*4)+2]?'X':'-', blank_tile_quarters_table[(t*4)+3]?'X':'-');
8570 jwin_alert("Blank Tile Information",tbuf,tbuf2,tbuf3,"&OK",NULL,13,27,get_zc_font(font_lfont));
8571 }
8572
8573 static void do_convert_tile(int32_t tile, int32_t tile2, int32_t cs, bool rect_sel, int format, bool shift, bool alt, bool skip_prompt = false)
8574 {
8575 int num_bits;
8576 if (format == tf4Bit)
8577 num_bits = 4;
8578 else if (format == tf8Bit)
8579 num_bits = 8;
8580 else assert(false);
8581
8582 char buf[80];
8583 sprintf(buf, "Do you want to convert the selected %s to %d-bit color?", tile==tile2?"tile":"tiles",num_bits);
8584
8585 if (skip_prompt || jwin_alert("Convert Tile?",buf,NULL,NULL,"&Yes","&No",'y','n',get_zc_font(font_lfont))==1)
8586 {
8587 go_tiles();
8588 saved=false;
8589
8590 if(format == tf4Bit)
8591 {
8592 memset(cset_reduce_table, 0, 256);
8593 memset(col_diff,0,3*128);
8594 calc_cset_reduce_table(RAMpal, cs);
8595 }
8596
8597 int32_t firsttile=zc_min(tile,tile2), lasttile=zc_max(tile,tile2), coldiff=0;
8598
8599 if(rect_sel && TILECOL(firsttile)>TILECOL(lasttile))
8600 {
8601 coldiff=TILECOL(firsttile)-TILECOL(lasttile);
8602 firsttile-=coldiff;
8603 lasttile+=coldiff;
8604 }
8605
8606 for(int32_t t=firsttile; t<=lasttile; t++)
8607 if(!rect_sel ||
8608 ((TILECOL(t)>=TILECOL(firsttile)) &&
8609 (TILECOL(t)<=TILECOL(lasttile))))
8610 convert_tile(t, format, cs, shift, alt);
8611
8612 tile=tile2=zc_min(tile,tile2);
8613 }
8614 }
8615
8616
8617 int32_t readtilefile(PACKFILE *f)
8618 {
8619 dword section_version=0;
8620 dword section_cversion=0;
8621 int32_t zversion = 0;
8622 int32_t zbuild = 0;
8623
8624 if(!p_igetl(&zversion,f))
8625 {
8626 return 0;
8627 }
8628 if(!p_igetl(&zbuild,f))
8629 {
8630 return 0;
8631 }
8632 if(!p_igetw(&section_version,f))
8633 {
8634 return 0;
8635 }
8636 if(!p_igetw(&section_cversion,f))
8637 {
8638 return 0;
8639 }
8640 al_trace("readoneweapon section_version: %d\n", section_version);
8641 al_trace("readoneweapon section_cversion: %d\n", section_cversion);
8642
8643 if ( zversion > ZELDA_VERSION )
8644 {
8645 al_trace("Cannot read .ztile packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
8646 return 0;
8647 }
8648
8649 else if ( ( section_version > V_TILES ) || ( section_version == V_TILES && section_cversion < CV_TILES ) )
8650 {
8651 al_trace("Cannot read .ztile packfile made using V_TILES (%d) subversion (%d)\n", section_version, section_cversion);
8652 return 0;
8653
8654 }
8655 else
8656 {
8657 al_trace("Reading a .ztile packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
8658 }
8659
8660 int32_t index = 0;
8661 int32_t count = 0;
8662
8663 //tile id
8664 if(!p_igetl(&index,f))
8665 {
8666 return 0;
8667 }
8668 al_trace("Reading tile: index(%d)\n", index);
8669
8670 //tile count
8671 if(!p_igetl(&count,f))
8672 {
8673 return 0;
8674 }
8675 al_trace("Reading tile: count(%d)\n", count);
8676
8677
8678
8679
8680 for ( int32_t tilect = 0; tilect < count; tilect++ )
8681 {
8682 byte *temp_tile = new byte[tilesize(tf32Bit)];
8683 byte format=tf4Bit;
8684 memset(temp_tile, 0, tilesize(tf32Bit));
8685 if(!p_getc(&format,f))
8686 {
8687 delete[] temp_tile;
8688 return 0;
8689 }
8690
8691
8692 if(!pfread(temp_tile,tilesize(format),f))
8693 {
8694 delete[] temp_tile;
8695 return 0;
8696 }
8697
8698 reset_tile(newtilebuf, index+(tilect), format);
8699 memcpy(newtilebuf[index+(tilect)].data,temp_tile,tilesize(newtilebuf[index+(tilect)].format));
8700 delete[] temp_tile;
8701 }
8702
8703
8704 //::memcpy(&(newtilebuf[tile_index]),&temptile,sizeof(tiledata));
8705
8706 register_blank_tiles();
8707 register_used_tiles();
8708
8709 return 1;
8710
8711 }
8712
8713 int32_t readtilefile_to_location(PACKFILE *f, int32_t start, int32_t skip)
8714 {
8715 dword section_version=0;
8716 dword section_cversion=0;
8717 int32_t zversion = 0;
8718 int32_t zbuild = 0;
8719
8720 if(!p_igetl(&zversion,f))
8721 {
8722 return 0;
8723 }
8724 if(!p_igetl(&zbuild,f))
8725 {
8726 return 0;
8727 }
8728 if(!p_igetw(&section_version,f))
8729 {
8730 return 0;
8731 }
8732 if(!p_igetw(&section_cversion,f))
8733 {
8734 return 0;
8735 }
8736 al_trace("readoneweapon section_version: %d\n", section_version);
8737 al_trace("readoneweapon section_cversion: %d\n", section_cversion);
8738
8739 if ( zversion > ZELDA_VERSION )
8740 {
8741 al_trace("Cannot read .ztile packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
8742 return 0;
8743 }
8744
8745 else if ( ( section_version > V_TILES ) || ( section_version == V_TILES && section_cversion < CV_TILES ) )
8746 {
8747 al_trace("Cannot read .ztile packfile made using V_TILES (%d) subversion (%d)\n", section_version, section_cversion);
8748 return 0;
8749
8750 }
8751 else
8752 {
8753 al_trace("Reading a .ztile packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
8754 }
8755
8756 int32_t index = 0;
8757 int32_t count = 0;
8758
8759 //tile id
8760 if(!p_igetl(&index,f))
8761 {
8762 return 0;
8763 }
8764 al_trace("Reading tile: index(%d)\n", index);
8765
8766 //tile count
8767 if(!p_igetl(&count,f))
8768 {
8769 return 0;
8770 }
8771 al_trace("Reading tile: count(%d)\n", count);
8772
8773
8774 for ( int32_t tilect = 0; tilect < count; tilect++ )
8775 {
8776 byte *temp_tile = new byte[tilesize(tf32Bit)];
8777 byte format=tf4Bit;
8778 memset(temp_tile, 0, tilesize(tf32Bit));
8779 if(!p_getc(&format,f))
8780 {
8781 delete[] temp_tile;
8782 return 0;
8783 }
8784
8785
8786 if(!pfread(temp_tile,tilesize(format),f))
8787 {
8788 delete[] temp_tile;
8789 return 0;
8790 }
8791
8792 reset_tile(newtilebuf, start+(tilect), format);
8793 if ( skip )
8794 {
8795 if ( (start+(tilect)) < skip )
8796 {
8797 delete[] temp_tile;
8798 continue;
8799 }
8800
8801 }
8802 if ( start+(tilect) < NEWMAXTILES )
8803 {
8804 memcpy(newtilebuf[start+(tilect)].data,temp_tile,tilesize(newtilebuf[start+(tilect)].format));
8805 }
8806 delete[] temp_tile;
8807
8808 }
8809
8810
8811 //::memcpy(&(newtilebuf[tile_index]),&temptile,sizeof(tiledata));
8812
8813 register_blank_tiles();
8814 register_used_tiles();
8815
8816 return 1;
8817
8818 }
8819
8820
8821 int32_t readtilefile_to_location(PACKFILE *f, int32_t start)
8822 {
8823 dword section_version=0;
8824 dword section_cversion=0;
8825 int32_t zversion = 0;
8826 int32_t zbuild = 0;
8827
8828 if(!p_igetl(&zversion,f))
8829 {
8830 return 0;
8831 }
8832 if(!p_igetl(&zbuild,f))
8833 {
8834 return 0;
8835 }
8836 if(!p_igetw(&section_version,f))
8837 {
8838 return 0;
8839 }
8840 if(!p_igetw(&section_cversion,f))
8841 {
8842 return 0;
8843 }
8844 al_trace("readoneweapon section_version: %d\n", section_version);
8845 al_trace("readoneweapon section_cversion: %d\n", section_cversion);
8846
8847 if ( zversion > ZELDA_VERSION )
8848 {
8849 al_trace("Cannot read .ztile packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
8850 return 0;
8851 }
8852
8853 else if ( ( section_version > V_TILES ) || ( section_version == V_TILES && section_cversion < CV_TILES ) )
8854 {
8855 al_trace("Cannot read .ztile packfile made using V_TILES (%d) subversion (%d)\n", section_version, section_cversion);
8856 return 0;
8857
8858 }
8859 else
8860 {
8861 al_trace("Reading a .ztile packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
8862 }
8863
8864 int32_t index = 0;
8865 int32_t count = 0;
8866
8867 //tile id
8868 if(!p_igetl(&index,f))
8869 {
8870 return 0;
8871 }
8872 al_trace("Reading tile: index(%d)\n", index);
8873
8874 //tile count
8875 if(!p_igetl(&count,f))
8876 {
8877 return 0;
8878 }
8879 al_trace("Reading tile: count(%d)\n", count);
8880
8881
8882
8883
8884 for ( int32_t tilect = 0; tilect < count; tilect++ )
8885 {
8886 byte *temp_tile = new byte[tilesize(tf32Bit)];
8887 byte format=tf4Bit;
8888 memset(temp_tile, 0, tilesize(tf32Bit));
8889
8890 if(!p_getc(&format,f))
8891 {
8892 delete[] temp_tile;
8893 return 0;
8894 }
8895
8896
8897 if(!pfread(temp_tile,tilesize(format),f))
8898 {
8899 delete[] temp_tile;
8900 return 0;
8901 }
8902
8903 reset_tile(newtilebuf, start+(tilect), format);
8904 if ( start+(tilect) < NEWMAXTILES )
8905 {
8906 memcpy(newtilebuf[start+(tilect)].data,temp_tile,tilesize(newtilebuf[start+(tilect)].format));
8907 }
8908 delete[] temp_tile;
8909 }
8910
8911
8912 //::memcpy(&(newtilebuf[tile_index]),&temptile,sizeof(tiledata));
8913
8914 register_blank_tiles();
8915 register_used_tiles();
8916
8917 return 1;
8918
8919 }
8920 int32_t writetilefile(PACKFILE *f, int32_t index, int32_t count)
8921 {
8922 dword section_version=V_TILES;
8923 dword section_cversion=CV_TILES;
8924 int32_t zversion = ZELDA_VERSION;
8925 int32_t zbuild = VERSION_BUILD;
8926
8927 if(!p_iputl(zversion,f))
8928 {
8929 return 0;
8930 }
8931 if(!p_iputl(zbuild,f))
8932 {
8933 return 0;
8934 }
8935 if(!p_iputw(section_version,f))
8936 {
8937 return 0;
8938 }
8939
8940 if(!p_iputw(section_cversion,f))
8941 {
8942 return 0;
8943 }
8944
8945 //start tile id
8946 if(!p_iputl(index,f))
8947 {
8948 return 0;
8949 }
8950
8951 //count
8952 if(!p_iputl(count,f))
8953 {
8954 return 0;
8955 }
8956
8957 for ( int32_t tilect = 0; tilect < count; tilect++ )
8958 {
8959 if(!p_putc(newtilebuf[index+(tilect)].format,f))
8960 {
8961 return 0;
8962 }
8963 if(!pfwrite(newtilebuf[index+(tilect)].data,tilesize(newtilebuf[index+(tilect)].format),f))
8964 {
8965 return 0;
8966 }
8967 }
8968
8969 return 1;
8970
8971 }
8972
8973 static int32_t _selected_tile=-1, _selected_tcset=-1;
8974 int32_t select_tile(int32_t &tile,int32_t &flip,int32_t type,int32_t &cs,bool edit_cs,int32_t exnow, bool always_use_flip)
8975 {
8976 popup_zqdialog_start();
8977 reset_combo_animations();
8978 reset_combo_animations2();
8979 bound(tile,0,NEWMAXTILES-1);
8980 ex=exnow;
8981 int32_t done=0;
8982 int32_t oflip=flip;
8983 int32_t otile=tile;
8984 int32_t ocs=cs;
8985 int32_t first=(tile/TILES_PER_PAGE)*TILES_PER_PAGE; //first tile on the current page
8986 int32_t copy=-1;
8987 int32_t tile2=tile,copycnt=0;
8988 int32_t tile_clicked=-1;
8989 bool rect_sel=true;
8990 bound(first,0,(TILES_PER_PAGE*TILE_PAGES)-1);
8991 position_mouse_z(0);
8992
8993 go();
8994
8995 register_used_tiles();
8996 int32_t w = 640;
8997 int32_t h = 480;
8998 int32_t window_xofs=(zq_screen_w-w-12)>>1;
8999 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
9000 int32_t screen_xofs=window_xofs+6;
9001 int32_t screen_yofs=window_yofs+25;
9002 int32_t panel_yofs=3;
9003 int32_t mul = 2;
9004 FONT *tfont = get_zc_font(font_lfont_l);
9005
9006 draw_tile_list_window();
9007 int32_t f=0;
9008 draw_tiles(first,cs,f);
9009
9010 if(type==0)
9011 {
9012 tile_info_0(tile,tile2,cs,copy,copycnt,first/TILES_PER_PAGE,rect_sel);
9013 }
9014 else
9015 {
9016 tile_info_1(otile,oflip,ocs,tile,flip,cs,copy,first/TILES_PER_PAGE, always_use_flip);
9017 }
9018
9019 go_tiles();
9020
9021 while(gui_mouse_b())
9022 {
9023 /* do nothing */
9024 rest(1);
9025 }
9026
9027 bool bdown=false;
9028
9029 #define FOREACH_START(_t) \
9030 { \
9031 int32_t _first, _last; \
9032 if(is_rect) \
9033 { \
9034 _first=top*TILES_PER_ROW+left; \
9035 _last=_first+rows*TILES_PER_ROW|+columns-1; \
9036 } \
9037 else \
9038 { \
9039 _first=zc_min(tile, tile2); \
9040 _last=zc_max(tile, tile2); \
9041 } \
9042 for(int32_t _t=_first; _t<=_last; _t++) \
9043 { \
9044 if(is_rect) \
9045 { \
9046 int32_t row=TILEROW(_t); \
9047 if(row<top || row>=top+rows) \
9048 continue; \
9049 int32_t col=TILECOL(_t); \
9050 if(col<left || col>=left+columns) \
9051 continue; \
9052 } \
9053
9054 #define FOREACH_END\
9055 } \
9056 }
9057
9058 bool did_snap = false;
9059 int otl = tile, otl2 = tile2;
9060 do
9061 {
9062 HANDLE_CLOSE_ZQDLG();
9063 if(exiting_program) break;
9064 rest(4);
9065 int32_t top=TILEROW(zc_min(tile, tile2));
9066 int32_t left=zc_min(TILECOL(tile), TILECOL(tile2));
9067 int32_t rows=TILEROW(zc_max(tile, tile2))-top+1;
9068 int32_t columns=zc_max(TILECOL(tile), TILECOL(tile2))-left+1;
9069 bool is_rect=(rows==1)||(columns==TILES_PER_ROW)||rect_sel;
9070 bool redraw=false;
9071
9072 if(mouse_z!=0)
9073 {
9074 sel_tile(tile,tile2,first,type,((mouse_z/abs(mouse_z))*(-1)*TILES_PER_PAGE));
9075 position_mouse_z(0);
9076 redraw=true;
9077 }
9078
9079 if(keypressed())
9080 {
9081 switch(readkey()>>8)
9082 {
9083 case KEY_ENTER_PAD:
9084 case KEY_ENTER:
9085 done=2;
9086 break;
9087
9088 case KEY_ESC:
9089 done=1;
9090 break;
9091
9092 case KEY_F1:
9093 onHelp();
9094 break;
9095
9096 case KEY_EQUALS:
9097 case KEY_PLUS_PAD:
9098 {
9099 if(CHECK_CTRL_CMD ||
9100 key[KEY_ALT] || key[KEY_ALTGR])
9101 {
9102 FOREACH_START(t)
9103 if(key[KEY_ALT] || key[KEY_ALTGR])
9104 shift_tile_colors(t, 16, false);
9105 else
9106 shift_tile_colors(t, 1, key[KEY_LSHIFT] || key[KEY_RSHIFT]);
9107 FOREACH_END
9108
9109 register_blank_tiles();
9110 }
9111 else if(edit_cs)
9112 cs = (cs<13) ? cs+1:0;
9113
9114 redraw=true;
9115 break;
9116 }
9117
9118 case KEY_Z:
9119 case KEY_F12:
9120 {
9121 if(!did_snap)
9122 {
9123 //Export tile page as screenshot
9124 PALETTE temppal;
9125 get_palette(temppal);
9126 BITMAP *tempbmp=create_bitmap_ex(8,16*TILES_PER_ROW, 16*TILE_ROWS_PER_PAGE);
9127 draw_tiles(tempbmp,first,cs,f,false,true);
9128 save_bitmap(getSnapName(), tempbmp, RAMpal);
9129 destroy_bitmap(tempbmp);
9130
9131 redraw = true;
9132 did_snap = true;
9133 }
9134 break;
9135 }
9136
9137 case KEY_S:
9138 {
9139 if(!prompt_for_new_file_compat("Save ZTILE(.ztile)", "ztile", NULL,datapath,false))
9140 break;
9141 PACKFILE *f=pack_fopen_password(temppath,F_WRITE, "");
9142 if(!f) break;
9143 al_trace("Saving tile: %d\n", tile);
9144 writetilefile(f,tile,1);
9145 pack_fclose(f);
9146 break;
9147 }
9148 case KEY_L:
9149 {
9150 if(!prompt_for_existing_file_compat("Load ZTILE(.ztile)", "ztile", NULL,datapath,false))
9151 break;
9152 PACKFILE *f=pack_fopen_password(temppath,F_READ, "");
9153 if(!f) break;
9154 al_trace("Saving tile: %d\n", tile);
9155 if (!readtilefile(f))
9156 {
9157 al_trace("Could not read from .ztile packfile %s\n", temppath);
9158 jwin_alert("ZTILE File: Error","Could not load the specified Tile.",NULL,NULL,"O&K",NULL,'k',0,get_zc_font(font_lfont));
9159 }
9160 else
9161 {
9162 jwin_alert("ZTILE File: Success!","Loaded the source tiles to your tile sheets!",NULL,NULL,"O&K",NULL,'k',0,get_zc_font(font_lfont));
9163 }
9164
9165 pack_fclose(f);
9166 //register_blank_tiles();
9167 //register_used_tiles();
9168 redraw=true;
9169 break;
9170 }
9171 case KEY_MINUS:
9172 case KEY_MINUS_PAD:
9173 {
9174 if(CHECK_CTRL_CMD ||
9175 key[KEY_ALT] || key[KEY_ALTGR])
9176 {
9177 FOREACH_START(t)
9178 if(key[KEY_ALT] || key[KEY_ALTGR])
9179 shift_tile_colors(t, -16, false);
9180 else
9181 shift_tile_colors(t, -1, key[KEY_LSHIFT] || key[KEY_RSHIFT]);
9182 FOREACH_END
9183
9184 register_blank_tiles();
9185 }
9186 else if(edit_cs)
9187 cs = (cs>0) ? cs-1:13;
9188
9189 redraw=true;
9190 break;
9191 }
9192
9193 case KEY_UP:
9194 {
9195 switch(((key[KEY_ALT] || key[KEY_ALTGR])?2:0)+((CHECK_CTRL_CMD)?1:0))
9196 {
9197 case 3: //ALT and CTRL
9198 case 2: //ALT
9199 if(is_rect)
9200 {
9201 saved=false;
9202 go_slide_tiles(columns, rows, top, left);
9203 int32_t bitcheck = newtilebuf[((top)*TILES_PER_ROW)+left].format;
9204 bool same = true;
9205
9206 for(int32_t d=0; d<columns; d++)
9207 {
9208 for(int32_t s=0; s<rows; s++)
9209 {
9210 int32_t t=((top+s)*TILES_PER_ROW)+left+d;
9211
9212 if(newtilebuf[t].format!=bitcheck) same = false;
9213 }
9214 }
9215
9216 if(!same) break;
9217
9218 // This used to do something. Too lazy to remove.
9219 // Can probably remove the above "same" check too.
9220 bitcheck = 2;
9221
9222 for(int32_t c=0; c<columns; c++)
9223 {
9224 for(int32_t r=0; r<rows; r++)
9225 {
9226 int32_t temptile=((top+r)*TILES_PER_ROW)+left+c;
9227 qword *src_pixelrow=(qword*)(newundotilebuf[temptile].data+(8*bitcheck));
9228 qword *dest_pixelrow=(qword*)(newtilebuf[temptile].data);
9229
9230 for(int32_t pixelrow=0; pixelrow<16*bitcheck; pixelrow++)
9231 {
9232 if(pixelrow==15*bitcheck)
9233 {
9234 int32_t srctile=temptile+TILES_PER_ROW;
9235 if(srctile>=NEWMAXTILES)
9236 srctile-=rows*TILES_PER_ROW;
9237 src_pixelrow=(qword*)(newtilebuf[srctile].data);
9238 }
9239
9240 *dest_pixelrow=*src_pixelrow;
9241 dest_pixelrow++;
9242 src_pixelrow++;
9243 }
9244 }
9245
9246 qword *dest_pixelrow=(qword*)(newtilebuf[((top+rows-1)*TILES_PER_ROW)+left+c].data+(120*bitcheck));
9247
9248 for(int32_t b=0; b<bitcheck; b++,dest_pixelrow++)
9249 {
9250 if((CHECK_CTRL_CMD))
9251 {
9252 *dest_pixelrow=0;
9253 }
9254 else
9255 {
9256 qword *src_pixelrow=(qword*)(newundotilebuf[(top*TILES_PER_ROW)+left+c].data+(8*b));
9257 *dest_pixelrow=*src_pixelrow;
9258 }
9259 }
9260 }
9261 }
9262
9263 register_blank_tiles();
9264 redraw=true;
9265 break;
9266
9267 case 1: //CTRL
9268 case 0: //None
9269 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?-1*(tile_page_row(tile)*TILES_PER_ROW):-TILES_PER_ROW);
9270 redraw=true;
9271
9272 default: //Others
9273 break;
9274 }
9275 }
9276 break;
9277
9278 case KEY_DOWN:
9279 {
9280 switch(((key[KEY_ALT] || key[KEY_ALTGR])?2:0)+((CHECK_CTRL_CMD)?1:0))
9281 {
9282 case 3: //ALT and CTRL
9283 case 2: //ALT
9284 if(is_rect)
9285 {
9286 saved=false;
9287 go_slide_tiles(columns, rows, top, left);
9288 int32_t bitcheck = newtilebuf[((top)*TILES_PER_ROW)+left].format;
9289 bool same = true;
9290
9291 for(int32_t c=0; c<columns; c++)
9292 {
9293 for(int32_t r=0; r<rows; r++)
9294 {
9295 int32_t t=((top+r)*TILES_PER_ROW)+left+c;
9296
9297 if(newtilebuf[t].format!=bitcheck) same = false;
9298 }
9299 }
9300
9301 if(!same) break;
9302
9303 // This used to do something. Too lazy to remove.
9304 // Can probably remove the above "same" check too.
9305 bitcheck = 2;
9306
9307 for(int32_t c=0; c<columns; c++)
9308 {
9309 for(int32_t r=rows-1; r>=0; r--)
9310 {
9311 int32_t temptile=((top+r)*TILES_PER_ROW)+left+c;
9312 qword *src_pixelrow=(qword*)(newundotilebuf[temptile].data+(112*bitcheck)+(8*(bitcheck-1)));
9313 qword *dest_pixelrow=(qword*)(newtilebuf[temptile].data+(120*bitcheck)+(8*(bitcheck-1)));
9314
9315 for(int32_t pixelrow=(8<<bitcheck)-1; pixelrow>=0; pixelrow--)
9316 {
9317 if(pixelrow<bitcheck)
9318 {
9319 int32_t srctile=temptile-TILES_PER_ROW;
9320 if(srctile<0)
9321 srctile+=rows*TILES_PER_ROW;
9322 qword *tempsrc=(qword*)(newtilebuf[srctile].data+(120*bitcheck)+(8*pixelrow));
9323 *dest_pixelrow=*tempsrc;
9324 //*dest_pixelrow=0;
9325 }
9326 else
9327 {
9328 *dest_pixelrow=*src_pixelrow;
9329 }
9330
9331 dest_pixelrow--;
9332 src_pixelrow--;
9333 }
9334 }
9335
9336 qword *dest_pixelrow=(qword*)(newtilebuf[(top*TILES_PER_ROW)+left+c].data);
9337 qword *src_pixelrow=(qword*)(newundotilebuf[((top+rows-1)*TILES_PER_ROW)+left+c].data+(120*bitcheck));
9338
9339 for(int32_t b=0; b<bitcheck; b++)
9340 {
9341 if((CHECK_CTRL_CMD))
9342 {
9343 *dest_pixelrow=0;
9344 }
9345 else
9346 {
9347 *dest_pixelrow=*src_pixelrow;
9348 }
9349
9350 dest_pixelrow++;
9351 src_pixelrow++;
9352 }
9353 }
9354 }
9355
9356 register_blank_tiles();
9357 redraw=true;
9358 break;
9359
9360 case 1: //CTRL
9361 case 0: //None
9362 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?((TILE_ROWS_PER_PAGE-1)-tile_page_row(tile))*TILES_PER_ROW:TILES_PER_ROW);
9363 redraw=true;
9364
9365 default: //Others
9366 break;
9367 }
9368 }
9369 break;
9370
9371 case KEY_LEFT:
9372 {
9373 switch(((key[KEY_ALT] || key[KEY_ALTGR])?2:0)+((CHECK_CTRL_CMD)?1:0))
9374 {
9375 case 3: //ALT and CTRL
9376 case 2: //ALT
9377 if(is_rect)
9378 {
9379 saved=false;
9380 go_slide_tiles(columns, rows, top, left);
9381 int32_t bitcheck = newtilebuf[((top)*TILES_PER_ROW)+left].format;
9382 bool same = true;
9383
9384 for(int32_t c=0; c<columns; c++)
9385 {
9386 for(int32_t r=0; r<rows; r++)
9387 {
9388 int32_t t=((top+r)*TILES_PER_ROW)+left+c;
9389
9390 if(newtilebuf[t].format!=bitcheck) same = false;
9391 }
9392 }
9393
9394 if(!same) break;
9395
9396 // This used to do something. Too lazy to remove.
9397 // Can probably remove the above "same" check too.
9398 bitcheck = 2;
9399
9400 for(int32_t r=0; r<rows; r++)
9401 {
9402 for(int32_t c=0; c<columns; c++)
9403 {
9404 int32_t temptile=((top+r)*TILES_PER_ROW)+left+c;
9405 byte *dest_pixelrow=(newtilebuf[temptile].data);
9406
9407 for(int32_t pixelrow=0; pixelrow<16; pixelrow++)
9408 {
9409 for(int32_t p=0; p<(8*bitcheck)-1; p++)
9410 {
9411 *dest_pixelrow=*(dest_pixelrow+1);
9412 dest_pixelrow++;
9413 }
9414
9415 if(c==columns-1)
9416 {
9417 if(!(CHECK_CTRL_CMD))
9418 {
9419 byte *tempsrc=(newundotilebuf[((top+r)*TILES_PER_ROW)+left].data+(pixelrow*8*bitcheck));
9420 *dest_pixelrow=*tempsrc;
9421 }
9422 }
9423 else
9424
9425 {
9426 byte *tempsrc=(newtilebuf[temptile+1].data+(pixelrow*8*bitcheck));
9427 *dest_pixelrow=*tempsrc;
9428 }
9429
9430 dest_pixelrow++;
9431 }
9432 }
9433 }
9434
9435 register_blank_tiles();
9436 redraw=true;
9437 }
9438
9439 break;
9440
9441 case 1: //CTRL
9442 case 0: //None
9443 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?-(tile%TILES_PER_ROW):-1);
9444 redraw=true;
9445
9446 default: //Others
9447 break;
9448 }
9449 }
9450 break;
9451
9452 case KEY_RIGHT:
9453 {
9454 switch(((key[KEY_ALT] || key[KEY_ALTGR])?2:0)+((CHECK_CTRL_CMD)?1:0))
9455 {
9456 case 3: //ALT and CTRL
9457 case 2: //ALT
9458 if(is_rect)
9459 {
9460 saved=false;
9461 go_slide_tiles(columns, rows, top, left);
9462 int32_t bitcheck = newtilebuf[((top)*TILES_PER_ROW)+left].format;
9463 bool same = true;
9464
9465 for(int32_t c=0; c<columns; c++)
9466 {
9467 for(int32_t r=0; r<rows; r++)
9468 {
9469 int32_t t=((top+r)*TILES_PER_ROW)+left+c;
9470
9471 if(newtilebuf[t].format!=bitcheck) same = false;
9472 }
9473 }
9474
9475 if(!same) break;
9476
9477 // This used to do something. Too lazy to remove.
9478 // Can probably remove the above "same" check too.
9479 bitcheck = 2;
9480
9481 for(int32_t r=0; r<rows; r++)
9482 {
9483 for(int32_t c=columns-1; c>=0; c--)
9484 {
9485 int32_t temptile=((top+r)*TILES_PER_ROW)+left+c;
9486 byte *dest_pixelrow=(newtilebuf[temptile].data)+(128*bitcheck)-1;
9487
9488 for(int32_t pixelrow=15; pixelrow>=0; pixelrow--)
9489 {
9490 for(int32_t p=0; p<(8*bitcheck)-1; p++)
9491 {
9492 *dest_pixelrow=*(dest_pixelrow-1);
9493 dest_pixelrow--;
9494 }
9495
9496 if(c==0)
9497 {
9498 if(!(CHECK_CTRL_CMD))
9499 {
9500 byte *tempsrc=(newundotilebuf[(((top+r)*TILES_PER_ROW)+left+columns-1)].data+(pixelrow*8*bitcheck)+(8*bitcheck)-1);
9501 *dest_pixelrow=*tempsrc;
9502 }
9503 }
9504 else
9505 {
9506 byte *tempsrc=(newtilebuf[temptile-1].data+(pixelrow*8*bitcheck)+(8*bitcheck)-1);
9507 *dest_pixelrow=*tempsrc;
9508 }
9509
9510 dest_pixelrow--;
9511 }
9512 }
9513 }
9514
9515 register_blank_tiles();
9516 redraw=true;
9517 }
9518
9519 break;
9520
9521 case 1: //CTRL
9522 case 0: //None
9523 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?(TILES_PER_ROW)-(tile%TILES_PER_ROW)-1:1);
9524 redraw=true;
9525
9526 default: //Others
9527 break;
9528 }
9529 }
9530 break;
9531
9532 case KEY_PGUP:
9533 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?-1*(TILEROW(tile)*TILES_PER_ROW):-TILES_PER_PAGE);
9534 redraw=true;
9535 break;
9536
9537 case KEY_PGDN:
9538 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?((TILE_PAGES*TILE_ROWS_PER_PAGE)-TILEROW(tile)-1)*TILES_PER_ROW:TILES_PER_PAGE);
9539 redraw=true;
9540 break;
9541
9542 case KEY_HOME:
9543 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?-(tile):-(tile%TILES_PER_PAGE));
9544 redraw=true;
9545 break;
9546
9547 case KEY_END:
9548 sel_tile(tile,tile2,first,type,(CHECK_CTRL_CMD)?(TILE_PAGES)*(TILES_PER_PAGE)-tile-1:(TILES_PER_PAGE)-(tile%TILES_PER_PAGE)-1);
9549 redraw=true;
9550 break;
9551
9552 case KEY_P:
9553 {
9554 int32_t whatPage = gettilepagenumber("Goto Page", (PreFillTileEditorPage?(first/TILES_PER_PAGE):0));
9555
9556 if(whatPage >= 0)
9557 sel_tile(tile,tile2,first,type,((whatPage-TILEPAGE(tile))*TILE_ROWS_PER_PAGE)*TILES_PER_ROW);
9558
9559 break;
9560 }
9561
9562 case KEY_O:
9563 if(type==0 && copy>=0)
9564 {
9565 go_tiles();
9566
9567 if(key[KEY_LSHIFT] ||key[KEY_RSHIFT])
9568 {
9569 mass_overlay_tile(zc_min(tile,tile2),zc_max(tile,tile2),copy,cs,(CHECK_CTRL_CMD), rect_sel);
9570 saved=false;
9571 }
9572 else
9573 {
9574 saved = !overlay_tiles(tile,tile2,copy,copycnt,rect_sel,false,cs,(CHECK_CTRL_CMD));
9575 //overlay_tile(newtilebuf,tile,copy,cs,(CHECK_CTRL_CMD));
9576 }
9577
9578 saved=false;
9579 redraw=true;
9580 }
9581
9582 break;
9583
9584 case KEY_E:
9585 if(type==0)
9586 {
9587 edit_tile(tile,flip,cs);
9588 draw_tile_list_window();
9589 redraw=true;
9590 }
9591
9592 break;
9593
9594 case KEY_G:
9595 if(type==0)
9596 {
9597 grab_tile(tile,cs);
9598 draw_tile_list_window();
9599 redraw=true;
9600 }
9601
9602 break;
9603
9604 case KEY_C:
9605 copy=zc_min(tile,tile2);
9606 copycnt=abs(tile-tile2)+1;
9607 redraw=true;
9608 break;
9609
9610 case KEY_X:
9611 if(type==2)
9612 {
9613 ex=(ex+1)%3;
9614 }
9615
9616 break;
9617
9618 case KEY_R:
9619 if(type==2)
9620 break;
9621 if(type==1)
9622 {
9623 flip = rotate_value(flip);
9624 redraw=true;
9625 break;
9626 }
9627
9628 go_tiles();
9629
9630 if(CHECK_CTRL_CMD)
9631 {
9632 bool go=false;
9633 if(key[KEY_LSHIFT] || key[KEY_RSHIFT])
9634 go=true;
9635 else if(massRecolorSetup(cs))
9636 go=true;
9637
9638 if(go)
9639 {
9640 FOREACH_START(t)
9641 massRecolorApply(t);
9642 FOREACH_END
9643
9644 register_blank_tiles();
9645 }
9646 }
9647 else
9648 {
9649 FOREACH_START(t)
9650 rotate_tile(t,(key[KEY_LSHIFT] || key[KEY_RSHIFT]));
9651 FOREACH_END
9652 }
9653
9654 redraw=true;
9655 saved=false;
9656 break;
9657
9658 case KEY_SPACE:
9659 rect_sel=!rect_sel;
9660 copy=-1;
9661 redraw=true;
9662 break;
9663
9664 case KEY_H:
9665 flip^=1;
9666 go_tiles();
9667
9668 if(type==0)
9669 {
9670 normalize(tile,tile2,rect_sel,flip);
9671 flip=0;
9672 }
9673
9674 redraw=true;
9675 break;
9676
9677
9678 case KEY_V:
9679 if(copy==-1)
9680 {
9681 if(type!=2)
9682 {
9683 flip^=2;
9684 go_tiles();
9685
9686 if(type==0)
9687 {
9688 normalize(tile,tile2,rect_sel,flip);
9689 flip=0;
9690 }
9691 }
9692 }
9693 else
9694 {
9695 bool alt=(key[KEY_ALT] || key[KEY_ALTGR]);
9696 go_tiles();
9697 saved = !copy_tiles(tile,tile2,copy,copycnt,rect_sel,false);
9698 }
9699
9700 redraw=true;
9701 break;
9702
9703 case KEY_F:
9704 if(copy==-1)
9705 {
9706 break;
9707 }
9708 else
9709 {
9710 go_tiles();
9711 {
9712 saved = !copy_tiles_floodfill(tile,tile2,copy,copycnt,rect_sel,false);
9713 }
9714 }
9715
9716 redraw=true;
9717 break;
9718
9719 case KEY_DEL:
9720 if(type==0 && (key[KEY_LSHIFT]||key[KEY_RSHIFT]))
9721 {
9722 bool warn = (rect_sel
9723 && ((tile/20)!=(tile2/20))
9724 && !(tile%20==0&&tile2%20==19));
9725 int32_t z=zc_min(tile,tile2);
9726 int32_t count = abs(tile-tile2) + 1;
9727 tile=z;
9728 tile2=NEWMAXTILES;
9729 copy = tile + count;
9730 copycnt = NEWMAXTILES-copy;
9731 char buf[64];
9732
9733 if(count>1)
9734 sprintf(buf,"Remove tiles %d - %d?",tile, copy-1);
9735 else
9736 sprintf(buf,"Remove tile %d?",tile);
9737
9738 AlertDialog("Remove Tiles", std::string(buf)
9739 +"\nThis will offset the tiles that follow!"
9740 +(warn?"\nRemoving tiles ignores rectangular selections!":""),
9741 [&](bool ret,bool)
9742 {
9743 if(ret)
9744 {
9745 go_tiles();
9746 if(copy_tiles(tile,tile2,copy,copycnt,false,true))
9747 {
9748 redraw=true;
9749 saved=false;
9750 }
9751 }
9752 }).show();
9753 }
9754 delete_tiles(tile,tile2,rect_sel);
9755 redraw=true;
9756 break;
9757
9758 case KEY_U:
9759 {
9760 if(CHECK_CTRL_CMD)
9761 {
9762 //Only toggle the first 2 bits!
9763 show_only_unused_tiles = (show_only_unused_tiles&~3) | (((show_only_unused_tiles&3)+1)%4);
9764 }
9765 else
9766 {
9767 comeback_tiles();
9768 }
9769
9770 redraw=true;
9771 }
9772 break;
9773
9774 case KEY_8:
9775 case KEY_8_PAD:
9776 hide_8bit_marker();
9777 break;
9778
9779 case KEY_I: //insert tiles
9780 if(type==0)
9781 {
9782 bool warn = (rect_sel
9783 && ((tile/20)!=(tile2/20))
9784 && !(tile%20==0&&tile2%20==19));
9785 int32_t z=zc_min(tile,tile2);
9786 int32_t count = abs(tile-tile2) + 1;
9787 tile=z;
9788 tile2=NEWMAXTILES;
9789 copy = tile + count;
9790 copycnt = NEWMAXTILES-copy;
9791
9792 if(key[KEY_LSHIFT]||key[KEY_RSHIFT]) //Remove
9793 {
9794 char buf[64];
9795
9796 if(count>1)
9797 sprintf(buf,"Remove tiles %d - %d?",tile, copy-1);
9798 else
9799 sprintf(buf,"Remove tile %d?",tile);
9800
9801 AlertDialog("Remove Tiles", std::string(buf)
9802 +"\nThis will offset the tiles that follow!"
9803 +(warn?"\nRemoving tiles ignores rectangular selections!":""),
9804 [&](bool ret,bool)
9805 {
9806 if(ret)
9807 {
9808 go_tiles();
9809 if(copy_tiles(tile,tile2,copy,copycnt,false,true))
9810 {
9811 redraw=true;
9812 saved=false;
9813 }
9814 }
9815 }).show();
9816 }
9817 else
9818 {
9819 char buf[64];
9820
9821 if(count>1)
9822 sprintf(buf,"Insert %d blank tiles?",count);
9823 else
9824 sprintf(buf,"Insert a blank tile?");
9825
9826 AlertDialog("Insert Tiles", std::string(buf)
9827 +"\nThis will offset the tiles that follow!"
9828 +(warn?"\nInserting tiles ignores rectangular selections!":""),
9829 [&](bool ret,bool)
9830 {
9831 if(ret)
9832 {
9833 go_tiles();
9834 if(copy_tiles(copy,tile2,tile,copycnt,false,true))
9835 {
9836 redraw=true;
9837 saved=false;
9838 }
9839 }
9840 }).show();
9841 }
9842
9843 copy=-1;
9844 tile2=tile=z;
9845 }
9846 break;
9847 case KEY_M:
9848 if(type==0)
9849 {
9850 if((copy!=-1)&&(copy!=zc_min(tile,tile2)))
9851 {
9852 go_tiles();
9853 if(copy_tiles(tile,tile2,copy,copycnt,rect_sel,true))
9854 saved=false;
9855 }
9856 else if(copy==-1)
9857 {
9858 // I don't know what this was supposed to be doing before.
9859 // It didn't work in anything like a sensible way.
9860 if(rect_sel)
9861 {
9862 make_combos_rect(top, left, rows, columns, cs);
9863 }
9864 else
9865 {
9866 make_combos(zc_min(tile, tile2), zc_max(tile, tile2), cs);
9867 }
9868 }
9869
9870 redraw=true;
9871 }
9872 break;
9873
9874 case KEY_D:
9875 {
9876 int32_t frames=1;
9877 char buf[80];
9878 sprintf(buf, "%d", frames);
9879 create_relational_tiles_dlg[0].dp2=get_zc_font(font_lfont);
9880 create_relational_tiles_dlg[2].dp=buf;
9881
9882 large_dialog(create_relational_tiles_dlg);
9883
9884 int32_t ret=do_zqdialog(create_relational_tiles_dlg,2);
9885
9886 if(ret==5)
9887 {
9888 frames=zc_max(atoi(buf),1);
9889 bool same = true;
9890 int32_t bitcheck=newtilebuf[tile].format;
9891
9892 for(int32_t t=1; t<frames*(create_relational_tiles_dlg[3].flags&D_SELECTED?6:19); ++t)
9893 {
9894 if(newtilebuf[tile+t].format!=bitcheck) same = false;
9895 }
9896
9897 if(!same)
9898 {
9899 jwin_alert("Error","The source tiles are not","in the same format.",NULL,"&OK",NULL,13,27,get_zc_font(font_lfont));
9900 break;
9901 }
9902
9903 if(tile+(frames*(create_relational_tiles_dlg[3].flags&D_SELECTED?48:96))>NEWMAXTILES)
9904 {
9905 jwin_alert("Error","Too many tiles will be created",NULL,NULL,"&OK",NULL,13,27,get_zc_font(font_lfont));
9906 break;
9907 }
9908
9909 for(int32_t i=frames*(create_relational_tiles_dlg[3].flags&D_SELECTED?6:19); i<(frames*(create_relational_tiles_dlg[3].flags&D_SELECTED?48:96)); ++i)
9910 {
9911 reset_tile(newtilebuf, tile+i, bitcheck);
9912 }
9913
9914 if(create_relational_tiles_dlg[3].flags&D_SELECTED)
9915 {
9916 for(int32_t i=create_relational_tiles_dlg[3].flags&D_SELECTED?47:95; i>0; --i)
9917 {
9918 for(int32_t j=0; j<frames; ++j)
9919 {
9920 merge_tiles(tile+(i*frames)+j, (tile+(relational_template[i][0]*frames)+j)<<2, ((tile+(relational_template[i][1]*frames)+j)<<2)+1, ((tile+(relational_template[i][2]*frames)+j)<<2)+2, ((tile+(relational_template[i][3]*frames)+j)<<2)+3);
9921 }
9922 }
9923 }
9924 else
9925 {
9926 for(int32_t i=create_relational_tiles_dlg[3].flags&D_SELECTED?47:95; i>0; --i)
9927 {
9928 for(int32_t j=0; j<frames; ++j)
9929 {
9930 merge_tiles(tile+(i*frames)+j, (tile+(dungeon_carving_template[i][0]*frames)+j)<<2, ((tile+(dungeon_carving_template[i][1]*frames)+j)<<2)+1, ((tile+(dungeon_carving_template[i][2]*frames)+j)<<2)+2, ((tile+(dungeon_carving_template[i][3]*frames)+j)<<2)+3);
9931 }
9932 }
9933 }
9934 }
9935 register_blank_tiles();
9936 register_used_tiles();
9937 redraw=true;
9938 saved=false;
9939 break;
9940 }
9941
9942 case KEY_B:
9943 {
9944 bool shift=(key[KEY_LSHIFT] || key[KEY_RSHIFT]);
9945 bool control=(CHECK_CTRL_CMD);
9946 bool alt=(key[KEY_ALT] || key[KEY_ALTGR]);
9947 int format = control ? tf4Bit : tf8Bit;
9948
9949 do_convert_tile(tile, tile2, cs, rect_sel, format, shift, alt);
9950 register_blank_tiles();
9951 }
9952 break;
9953 }
9954
9955 clear_keybuf();
9956 }
9957
9958 if(!(key[KEY_Z] || key[KEY_F12]))
9959 did_snap = false;
9960
9961 if(gui_mouse_b()&1)
9962 {
9963 if(isinRect(gui_mouse_x(),gui_mouse_y(),window_xofs + w + 12 - 21, window_yofs + 5, window_xofs + w +12 - 21 + 15, window_yofs + 5 + 13))
9964 {
9965 if(do_x_button(screen, w+12+window_xofs - 21, 5+window_yofs))
9966 {
9967 done=1;
9968 }
9969 }
9970
9971 int32_t x=gui_mouse_x()-screen_xofs;
9972 int32_t y=gui_mouse_y()-screen_yofs;
9973
9974 if(y>=0 && y<208*mul)
9975 {
9976 x=zc_min(zc_max(x,0),(320*mul)-1);
9977 int32_t t = (y>>(5))*TILES_PER_ROW + (x>>(5)) + first;
9978
9979 if(type==0 && (key[KEY_LSHIFT] || key[KEY_RSHIFT]))
9980 {
9981 tile2=t;
9982 }
9983 else
9984 {
9985 tile=tile2=t;
9986 }
9987
9988 if(tile_clicked!=t)
9989 {
9990 dclick_status=DCLICK_NOT;
9991 }
9992 else if(dclick_status == DCLICK_AGAIN)
9993 {
9994 while(gui_mouse_b())
9995 {
9996 /* do nothing */
9997 rest(1);
9998 }
9999
10000 if(((y>>(5))*TILES_PER_ROW + (x>>(5)) + first)!=t)
10001 {
10002 dclick_status=DCLICK_NOT;
10003 }
10004 else
10005 {
10006 if(type==0)
10007 {
10008 edit_tile(tile,flip,cs);
10009 draw_tile_list_window();
10010 redraw=true;
10011 }
10012 else
10013 {
10014 done=2;
10015 }
10016 }
10017 }
10018
10019 tile_clicked=t;
10020 }
10021 else if(x>300*mul && !bdown)
10022 {
10023 if(y<224*mul && first>0)
10024 {
10025 first-=TILES_PER_PAGE;
10026 redraw=true;
10027 }
10028
10029 if(y>=224*mul && first<TILES_PER_PAGE*(TILE_PAGES-1))
10030 {
10031 first+=TILES_PER_PAGE;
10032 redraw=true;
10033 }
10034
10035 bdown=true;
10036 }
10037
10038 if(type==1||type==2)
10039 {
10040 if(!bdown && isinRect(x,y,8*mul,216*mul+panel_yofs,23*mul,231*mul+panel_yofs))
10041 done=1;
10042
10043 if(!bdown && isinRect(x,y,148*mul,216*mul+panel_yofs,163*mul,231*mul+panel_yofs))
10044 done=2;
10045 }
10046 else if(!bdown && isinRect(x,y,127*mul,216*mul+panel_yofs,(127+15)*mul,(216+15)*mul+panel_yofs))
10047 {
10048 rect_sel=!rect_sel;
10049 copy=-1;
10050 redraw=true;
10051 }
10052 else if(!bdown && isinRect(x,y,150*mul,213*mul+panel_yofs,(150+28)*mul,(213+21)*mul+panel_yofs))
10053 {
10054 FONT *tf = font;
10055 font = tfont;
10056
10057 if(do_text_button(150*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"&Grab"))
10058 {
10059 font = tf;
10060 grab_tile(tile,cs);
10061 draw_tile_list_window();
10062 position_mouse_z(0);
10063 redraw=true;
10064 }
10065
10066 font = tf;
10067 }
10068 else if(!bdown && isinRect(x,y,(150+28)*mul,213*mul+panel_yofs,(150+28*2)*mul,(213+21)*mul+panel_yofs+21))
10069 {
10070 FONT *tf = font;
10071 font = tfont;
10072
10073 if(do_text_button((150+28)*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"&Edit"))
10074 {
10075 font = tf;
10076 edit_tile(tile,flip,cs);
10077 draw_tile_list_window();
10078 redraw=true;
10079 }
10080
10081 font = tf;
10082 }
10083 else if(!bdown && isinRect(x,y,(150+28*2)*mul,213*mul+panel_yofs,(150+28*3)*mul,(213+21)*mul+panel_yofs))
10084 {
10085 FONT *tf = font;
10086 font = tfont;
10087
10088 if(do_text_button((150+28*2)*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"Export"))
10089 {
10090 std::string initial_path = "tileset.png";
10091 if (strlen(datapath))
10092 initial_path = fmt::format("{}/{}", datapath, initial_path);
10093 if(prompt_for_new_file_compat("Export Tile Page (.png)","png",NULL,initial_path,true))
10094 {
10095 PALETTE temppal;
10096 get_palette(temppal);
10097 BITMAP *tempbmp=create_bitmap_ex(8,16*TILES_PER_ROW, 16*TILE_ROWS_PER_PAGE);
10098 draw_tiles(tempbmp,first,cs,f,false,true);
10099 save_bitmap(temppath, tempbmp, RAMpal);
10100 destroy_bitmap(tempbmp);
10101 }
10102 }
10103
10104 font = tf;
10105 }
10106 else if(!bdown && isinRect(x,y,(150+28*3)*mul,213*mul+panel_yofs,(150+28*4)*mul,(213+21)*mul+panel_yofs))
10107 {
10108 FONT *tf = font;
10109 font = tfont;
10110
10111 if(do_text_button((150+28*3)*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"Recolor"))
10112 {
10113 if(massRecolorSetup(cs))
10114 {
10115 go_tiles();
10116
10117 FOREACH_START(t)
10118 massRecolorApply(t);
10119 FOREACH_END
10120
10121 register_blank_tiles();
10122 }
10123 }
10124
10125 font = tf;
10126 }
10127 else if(!bdown && isinRect(x,y,(150+28*4)*mul,213*mul+panel_yofs,(150+28*5)*mul,(213+21)*mul+panel_yofs))
10128 {
10129 FONT *tf = font;
10130 font = tfont;
10131
10132 if(do_text_button((150+28*4)*mul+screen_xofs,213*mul+screen_yofs+panel_yofs,28*mul,21*mul,"Done"))
10133 {
10134 done=1;
10135 }
10136
10137 font = tf;
10138 }
10139
10140 bdown=true;
10141 }
10142
10143 bool r_click = false;
10144
10145 if(gui_mouse_b()&2 && !bdown && type==0)
10146 {
10147 int32_t x=(gui_mouse_x()-screen_xofs);//&0xFF0;
10148 int32_t y=(gui_mouse_y()-screen_yofs);//&0xF0;
10149
10150 if(y>=0 && y<208*mul)
10151 {
10152 x=zc_min(zc_max(x,0),(320*mul)-1);
10153 int32_t t = ((y)>>(5))*TILES_PER_ROW + ((x)>>(5)) + first;
10154
10155 if(t<zc_min(tile,tile2) || t>zc_max(tile,tile2))
10156 tile=tile2=t;
10157 }
10158
10159 bdown = r_click = true;
10160 f=8;
10161 }
10162
10163 if(gui_mouse_b()==0)
10164 bdown=false;
10165
10166 position_mouse_z(0);
10167
10168 REDRAW:
10169
10170 if((f%8)==0 || InvalidBG == 1)
10171 redraw=true;
10172 if(otl != tile || otl2 != tile2)
10173 {
10174 otl = tile;
10175 otl2 = tile2;
10176 redraw = true;
10177 }
10178
10179 if(redraw)
10180 {
10181 draw_tiles(first,cs,f);
10182 }
10183 if(f&8)
10184 {
10185 if(rect_sel)
10186 {
10187 for(int32_t i=zc_min(TILEROW(tile),TILEROW(tile2))*TILES_PER_ROW+
10188 zc_min(TILECOL(tile),TILECOL(tile2));
10189 i<=zc_max(TILEROW(tile),TILEROW(tile2))*TILES_PER_ROW+
10190 zc_max(TILECOL(tile),TILECOL(tile2)); i++)
10191 {
10192 if(i>=first && i<first+TILES_PER_PAGE &&
10193 TILECOL(i)>=zc_min(TILECOL(tile),TILECOL(tile2)) &&
10194 TILECOL(i)<=zc_max(TILECOL(tile),TILECOL(tile2)))
10195 {
10196 int32_t x=TILECOL(i)<<(5);
10197 int32_t y=TILEROW(i-first)<<(5);
10198 safe_rect(screen2,x,y,x+(16*mul)-1,y+(16*mul)-1,vc(TilePgCursorCol),2);
10199 }
10200 }
10201 }
10202 else
10203 {
10204 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
10205 {
10206 if(i>=first && i<first+TILES_PER_PAGE)
10207 {
10208 int32_t x=TILECOL(i)<<(5);
10209 int32_t y=TILEROW(i-first)<<(5);
10210 safe_rect(screen2,x,y,x+(16*mul)-1,y+(16*mul)-1,vc(TilePgCursorCol),2);
10211 }
10212 }
10213 }
10214 }
10215
10216 if(type==0)
10217 tile_info_0(tile,tile2,cs,copy,copycnt,first/TILES_PER_PAGE,rect_sel);
10218 else
10219 tile_info_1(otile,oflip,ocs,tile,flip,cs,copy,first/TILES_PER_PAGE, always_use_flip);
10220
10221 if(type==2)
10222 {
10223 char cbuf[16];
10224 sprintf(cbuf, "E&xtend: %s",ex==2 ? "32x32" : ex==1 ? "32x16" : "16x16");
10225 gui_textout_ln(screen, get_zc_font(font_lfont_l), (uint8_t *)cbuf, (235*mul)+screen_xofs, (212*mul)+screen_yofs+panel_yofs, jwin_pal[jcBOXFG],jwin_pal[jcBOX],0);
10226 }
10227
10228 ++f;
10229
10230 if(r_click)
10231 {
10232 select_tile_view_menu.select_uid(MENUID_SELTILE_VIEW_HIDE_USED, HIDE_USED);
10233 select_tile_view_menu.select_uid(MENUID_SELTILE_VIEW_HIDE_UNUSED, HIDE_UNUSED);
10234 select_tile_view_menu.select_uid(MENUID_SELTILE_VIEW_HIDE_BLANK, HIDE_BLANK);
10235 select_tile_view_menu.select_uid(MENUID_SELTILE_VIEW_HIDE_8BIT, HIDE_8BIT_MARKER);
10236
10237 int current_tile_format = MENUID_SELTILE_COLOR_DEPTH_4_BIT;
10238 if (newtilebuf[tile].format == tf8Bit)
10239 current_tile_format = MENUID_SELTILE_COLOR_DEPTH_8_BIT;
10240 select_tile_color_depth_menu.select_only_uid(current_tile_format);
10241 select_tile_color_depth_cb = [&](int format){
10242 if (newtilebuf[tile].format == format)
10243 return;
10244
10245 bool skip_prompt = true;
10246 do_convert_tile(tile, tile2, cs, rect_sel, format, false, false, skip_prompt);
10247 };
10248
10249 NewMenu rcmenu
10250 {
10251 { "Copy", [&]()
10252 {
10253 copy = zc_min(tile,tile2);
10254 copycnt = abs(tile-tile2)+1;
10255 } },
10256 { "Paste", [&]()
10257 {
10258 bool b = copy_tiles(tile, tile2, copy, copycnt, rect_sel, false);
10259 if(saved) saved = !b;
10260 }, nullopt, copy < 0 },
10261 { "Move", [&]()
10262 {
10263 bool b = copy_tiles(tile, tile2, copy, copycnt, rect_sel, true);
10264 if(saved) saved = !b;
10265 }, nullopt, copy < 0 },
10266 { "Clear", [&]()
10267 {
10268 delete_tiles(tile, tile2, rect_sel);
10269 } },
10270 {},
10271 { "Edit", [&]()
10272 {
10273 edit_tile(tile, flip, cs);
10274 draw_tile_list_window();
10275 } },
10276 { "Grab", [&]()
10277 {
10278 grab_tile(tile, cs);
10279 draw_tile_list_window();
10280 position_mouse_z(0);
10281 } },
10282 { "Scale", [&]()
10283 {
10284 bool b = scale_or_rotate_tiles(tile, tile2, cs, false);
10285 if(saved) saved = !b;
10286 }, nullopt, type != 0 },
10287 { "Angular Rotation", [&]()
10288 {
10289 bool b = scale_or_rotate_tiles(tile, tile2, cs, true);
10290 if(saved) saved = !b;
10291 }, nullopt, type != 0 },
10292 { "Color Depth", &select_tile_color_depth_menu },
10293 {},
10294 { "Blank?", [&]()
10295 {
10296 show_blank_tile(tile);
10297 } },
10298 {},
10299 { "View ", &select_tile_view_menu },
10300 { "Overlay", [&]()
10301 {
10302 overlay_tile(newtilebuf, tile, copy, cs, 0);
10303 } },
10304 { "H-Flip", [&]()
10305 {
10306 flip ^= 1;
10307 go_tiles();
10308
10309 if(type == 0)
10310 {
10311 normalize(tile, tile2, rect_sel, flip);
10312 flip = 0;
10313 }
10314 } },
10315 { "V-Flip", [&]()
10316 {
10317 flip ^= 2;
10318 go_tiles();
10319
10320 if(type == 0)
10321 {
10322 normalize(tile, tile2, rect_sel, flip);
10323 flip = 0;
10324 }
10325 } },
10326 { "Create Combos", [&]()
10327 {
10328 if(rect_sel)
10329 make_combos_rect(top, left, rows, columns, cs);
10330 else
10331 make_combos(zc_min(tile, tile2), zc_max(tile, tile2), cs);
10332 }, nullopt, type != 0 },
10333 { "Insert", [&]()
10334 {
10335 bool warn = (rect_sel
10336 && ((tile/20)!=(tile2/20))
10337 && !(tile%20==0&&tile2%20==19));
10338 int32_t z = zc_min(tile, tile2);
10339 int32_t count = abs(tile-tile2) + 1;
10340 tile = z;
10341 tile2 = NEWMAXTILES;
10342 copy = tile + count;
10343 copycnt = NEWMAXTILES-copy;
10344
10345 string msg;
10346
10347 if(count>1)
10348 msg = fmt::format("Insert {} blank tiles?",count);
10349 else
10350 msg = "Insert a blank tile?";
10351
10352 AlertDialog("Insert Tiles", msg
10353 +"\nThis will offset the tiles that follow!"
10354 +(warn?"\nInserting tiles ignores rectangular selections!":""),
10355 [&](bool ret,bool)
10356 {
10357 if(ret)
10358 {
10359 go_tiles();
10360 if(copy_tiles(copy, tile2, tile, copycnt, false, true))
10361 saved = false;
10362 }
10363 }).show();
10364
10365 copy=-1;
10366 tile2=tile=z;
10367 }, nullopt, type != 0 },
10368 { "Remove", [&]()
10369 {
10370 bool warn = (rect_sel
10371 && ((tile/20)!=(tile2/20))
10372 && !(tile%20==0&&tile2%20==19));
10373 int32_t z = zc_min(tile, tile2);
10374 int32_t count = abs(tile-tile2) + 1;
10375 tile = z;
10376 tile2 = NEWMAXTILES;
10377 copy = tile + count;
10378 copycnt = NEWMAXTILES-copy;
10379
10380 string msg;
10381
10382 if(count>1)
10383 msg = fmt::format("Remove tiles {} - {}?", tile, copy-1);
10384 else
10385 msg = fmt::format("Remove tile {}?", tile);
10386
10387 AlertDialog("Remove Tiles", msg
10388 +"\nThis will offset the tiles that follow!"
10389 +(warn?"\nRemoving tiles ignores rectangular selections!":""),
10390 [&](bool ret,bool)
10391 {
10392 if(ret)
10393 {
10394 go_tiles();
10395 if(copy_tiles(tile, tile2, copy, copycnt, false, true))
10396 saved = false;
10397 }
10398 }).show();
10399
10400 copy=-1;
10401 tile2=tile=z;
10402 }, nullopt, type != 0 },
10403 };
10404 rcmenu.pop(window_mouse_x(),window_mouse_y());
10405 redraw = true;
10406 r_click = false;
10407 goto REDRAW;
10408 }
10409 update_hw_screen();
10410 }
10411 while(!done);
10412
10413 while(gui_mouse_b())
10414 {
10415 /* do nothing */
10416 rest(1);
10417 }
10418
10419 comeback();
10420 register_blank_tiles();
10421 register_used_tiles();
10422 setup_combo_animations();
10423 setup_combo_animations2();
10424 int32_t ret = done-1;
10425 if(ret)
10426 {
10427 _selected_tile = tile;
10428 _selected_tcset = cs;
10429 }
10430
10431 popup_zqdialog_end();
10432 return ret;
10433 }
10434 int32_t select_tile_2(int32_t &tile,int32_t &flip,int32_t type,int32_t &cs,bool edit_cs,int32_t exnow, bool always_use_flip)
10435 {
10436 if(_selected_tile > -1)
10437 {
10438 tile = _selected_tile;
10439 cs = _selected_tcset;
10440 }
10441 int32_t ret = select_tile(tile,flip,type,cs,edit_cs,exnow,always_use_flip);
10442 if(_selected_tile < 0)
10443 {
10444 _selected_tile = tile;
10445 _selected_tcset = cs;
10446 }
10447 return ret;
10448 }
10449
10450 int32_t onTiles()
10451 {
10452 return onGotoTiles(-1);
10453 }
10454
10455 int32_t onGotoTiles(int32_t startfrom)
10456 {
10457 static int32_t t = 0;
10458 if (startfrom > -1)
10459 t = startfrom;
10460 int32_t f = 0;
10461 int32_t c = CSet;
10462 reset_pal_cycling();
10463 // loadlvlpal(Map.CurrScr()->color);
10464 rebuild_trans_table();
10465 select_tile(t, f, 0, c, true);
10466 refresh(rALL);
10467 return D_O_K;
10468 }
10469
10470 int32_t combopage_animate = 1;
10471 void draw_combo(BITMAP *dest, int x,int y,int c,int cs,bool animate)
10472 {
10473 if(unsigned(c)<MAXCOMBOS)
10474 {
10475 newcombo& cmb = combobuf[c];
10476 int t = cmb.tile;
10477 if(!animate)
10478 cmb.tile = cmb.o_tile;
10479 put_combo(dest,x,y,c,cs,0,0);
10480 cmb.tile = t;
10481 }
10482 else
10483 {
10484 rectfill(dest,x,y,x+32-1,y+32-1,0);
10485 }
10486 }
10487
10488 void draw_combos(int32_t page,int32_t cs,bool cols)
10489 {
10490 clear_bitmap(screen2);
10491 BITMAP *buf = create_bitmap_ex(8,16,16);
10492
10493 int32_t w = 32;
10494 int32_t h = 32;
10495 int32_t mul = 2;
10496
10497 int32_t window_xofs=(zq_screen_w-640-12)>>1;
10498 int32_t window_yofs=(zq_screen_h-480-25-6)>>1;
10499 int32_t screen_xofs=window_xofs+6;
10500 int32_t screen_yofs=window_yofs+25;
10501
10502 if(cols==false)
10503 {
10504 for(int32_t i=0; i<256; i++) // 13 rows, leaving 32 pixels from y=208 to y=239
10505 {
10506 int32_t x = (i%COMBOS_PER_ROW)*w;
10507 int32_t y = (i/COMBOS_PER_ROW)*h;
10508
10509 combotile_override_x = x+screen_xofs+(w-16)/2;
10510 combotile_override_y = y+screen_yofs+(h-16)/2;
10511 draw_combo(buf,0,0,i+(page<<8),cs,combopage_animate);
10512 stretch_blit(buf,screen2,0,0,16,16,x,y,w,h);
10513 }
10514 }
10515 else
10516 {
10517 int32_t c = 0;
10518
10519 for(int32_t i=0; i<256; i++)
10520 {
10521 int32_t x = (i%COMBOS_PER_ROW)*w;
10522 int32_t y = (i/COMBOS_PER_ROW)*h;
10523
10524 combotile_override_x = x+screen_xofs+(w-16)/2;
10525 combotile_override_y = y+screen_yofs+(h-16)/2;
10526 draw_combo(buf,0,0,c+(page<<8),cs,combopage_animate);
10527 stretch_blit(buf,screen2,0,0,16,16,x,y,w,h);
10528 ++c;
10529
10530 if((i&3)==3)
10531 c+=48;
10532
10533 if((i%COMBOS_PER_ROW)==(COMBOS_PER_ROW-1))
10534 c-=256;
10535 }
10536 }
10537 combotile_override_x = combotile_override_y = -1;
10538
10539 for(int32_t x=(64*mul); x<(320*mul); x+=(64*mul))
10540 {
10541 vline(screen2,x,0,(208*mul)-1,vc(15));
10542 }
10543
10544 destroy_bitmap(buf);
10545 }
10546
10547 void combo_info(int32_t tile,int32_t tile2,int32_t cs,int32_t copy,int32_t copycnt,int32_t page,int32_t buttons)
10548 {
10549 int32_t yofs=3;
10550 static BITMAP *buf = create_bitmap_ex(8,16,16);
10551 int32_t mul = 2;
10552 FONT *tfont = get_zc_font(font_lfont_l);
10553
10554 rectfill(screen2,0,210*2,(320*2)-1,(240*2)-1,jwin_pal[jcBOX]);
10555 hline(screen2, 0, (210*2)-2, (320*2)-1, jwin_pal[jcMEDLT]);
10556 hline(screen2, 0, (210*2)-1, (320*2)-1, jwin_pal[jcLIGHT]);
10557
10558 jwin_draw_frame(screen2,(31*mul)-2,((216*mul)+yofs)-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
10559
10560 if(copy>=0)
10561 {
10562 put_combo(buf,0,0,copy,cs,0,0);
10563 stretch_blit(buf,screen2,0,0,16,16,31*mul,216*mul+yofs,16*mul,16*mul);
10564
10565 if(copycnt>1)
10566 {
10567 textprintf_right_ex(screen2,tfont,28*mul,(216*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d-",copy);
10568 textprintf_right_ex(screen2,tfont,24*mul,(224*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",copy+copycnt-1);
10569 }
10570 else
10571 {
10572 textprintf_right_ex(screen2,tfont,24*mul,(220*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",copy);
10573 }
10574 }
10575 else
10576 {
10577 if (InvalidBG == 2)
10578 {
10579 draw_checkerboard(screen2, 31 * mul, 216 * mul + yofs, 16 * mul);
10580 }
10581 else if(InvalidBG == 1)
10582 {
10583 for(int32_t dy=0; dy<16*mul; dy++)
10584 {
10585 for(int32_t dx=0; dx<16*mul; dx++)
10586 {
10587 screen2->line[(216*mul)+yofs+dy][(31*mul)+dx]=vc((((zc_oldrand()%100)/50)?0:8)+(((zc_oldrand()%100)/50)?0:7));
10588 }
10589 }
10590 }
10591 else
10592 {
10593 rectfill(screen2, (31*mul), (216*mul)+yofs, (31*mul)+31, (216*mul)+yofs+31, vc(0));
10594 rect(screen2, (31*mul), (216*mul)+yofs, (31*mul)+31, (216*mul)+yofs+31, vc(15));
10595 line(screen2, (31*mul), (216*mul)+yofs, (31*mul)+31, (216*mul)+yofs+31, vc(15));
10596 line(screen2, (31*mul), (216*mul)+yofs+31, (31*mul)+31, (216*mul)+yofs, vc(15));
10597 }
10598 }
10599
10600 jwin_draw_frame(screen2,(53*mul)-2,(216*mul)+yofs-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
10601 put_combo(buf,0,0,tile,cs,0,0);
10602 stretch_blit(buf,screen2,0,0,16,16,53*mul,216*mul+yofs,16*mul,16*mul);
10603
10604 if(tile>tile2)
10605 {
10606 zc_swap(tile,tile2);
10607 }
10608
10609 char cbuf[8];
10610 cbuf[0]=0;
10611
10612 if(tile2!=tile)
10613 {
10614 sprintf(cbuf,"-%d",tile2);
10615 }
10616
10617 textprintf_ex(screen2,tfont,(73*mul),(216*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"combo: CSet %d", cs);
10618 textprintf_ex(screen2,tfont,(73*mul),(224*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d%s",tile,cbuf);
10619
10620 if(tile2==tile)
10621 {
10622 int32_t nextcombo=combobuf[tile].nextcombo;
10623 int32_t nextcset=(combobuf[tile].animflags & AF_CYCLENOCSET) ? cs : combobuf[tile].nextcset;
10624 jwin_draw_frame(screen2,(136*mul)-2,(216*mul)+yofs-2,(16*mul)+4,(16*mul)+4,FR_DEEP);
10625
10626 if(nextcombo>0 && !(combobuf[tile].animflags & AF_CYCLEUNDERCOMBO))
10627 {
10628 put_combo(buf,0,0,nextcombo,nextcset,0,0);
10629 stretch_blit(buf,screen2,0,0,16,16,136*mul,216*mul+yofs,16*mul,16*mul);
10630 }
10631 else
10632 {
10633 if (InvalidBG == 2)
10634 {
10635 draw_checkerboard(screen2, 136 * mul, 216 * mul + yofs, 16 * mul);
10636 }
10637 else if(InvalidBG == 1)
10638 {
10639 for(int32_t dy=0; dy<16*mul; dy++)
10640 {
10641 for(int32_t dx=0; dx<16*mul; dx++)
10642 {
10643 screen2->line[(216*mul)+yofs+dy][(136*mul)+dx]=vc((((zc_oldrand()%100)/50)?0:8)+(((zc_oldrand()%100)/50)?0:7));
10644 }
10645 }
10646 }
10647 else
10648 {
10649 rectfill(screen2, (136*mul), (216*mul)+yofs, (136*mul)+31, (216*mul)+yofs+31, vc(0));
10650 rect(screen2, (136*mul), (216*mul)+yofs, (136*mul)+31, (216*mul)+yofs+31, vc(15));
10651 line(screen2, (136*mul), (216*mul)+yofs, (136*mul)+31, (216*mul)+yofs+31, vc(15));
10652 line(screen2, (136*mul), (216*mul)+yofs+31, (136*mul)+31, (216*mul)+yofs, vc(15));
10653 }
10654 }
10655
10656 textprintf_right_ex(screen2,tfont,(132*mul),(216*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Cycle:");
10657 textprintf_right_ex(screen2,tfont,(132*mul),(224*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",nextcombo);
10658 }
10659
10660
10661 FONT *tf = font;
10662 font = tfont;
10663
10664 draw_checkbox(screen2,320,440+yofs,16,combopage_animate);
10665 textprintf_ex(screen2,tfont,320+18,440+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Animate");
10666
10667 if(buttons&2)
10668 {
10669 draw_text_button(screen2,404,426+yofs,88,42,"Edit",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
10670 }
10671
10672 if(buttons&4)
10673 {
10674 draw_text_button(screen2,494,426+yofs,88,42,"Done",jwin_pal[jcBOXFG],jwin_pal[jcBOX],0,true);
10675 }
10676
10677 font = tf;
10678
10679 jwin_draw_icon(screen2,(305*mul+4),220*mul-6+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_UP,6,true);
10680 textprintf_ex(screen2,tfont,(293*mul),(220*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"p:");
10681 textprintf_centre_ex(screen2,tfont,(309*mul),(220*mul)+yofs,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",page);
10682 jwin_draw_icon(screen2,(305*mul+4),228*mul+3+yofs,jwin_pal[jcBOXFG],BTNICON_ARROW_DOWN,6,true);
10683
10684 int32_t w = 640;
10685 int32_t h = 480;
10686 int32_t window_xofs=(zq_screen_w-w-12)>>1;
10687 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
10688 int32_t screen_xofs=window_xofs+6;
10689 int32_t screen_yofs=window_yofs+25;
10690
10691 custom_vsync();
10692 blit(screen2,screen,0,0,screen_xofs,screen_yofs,w,h);
10693 SCRFIX();
10694 //destroy_bitmap(buf);
10695 }
10696
10697 void sel_combo(int32_t &tile, int32_t &tile2, int32_t s, bool cols)
10698 {
10699 int32_t page = tile&0xFF00;
10700 tile &= 0xFF;
10701
10702 if(!cols)
10703 tile += s;
10704 else
10705 {
10706 if(s==-COMBOS_PER_ROW)
10707 tile-=4;
10708
10709 if(s==COMBOS_PER_ROW)
10710 tile+=4;
10711
10712 if(s==-1)
10713 tile-=1;
10714
10715 if(s==1)
10716 tile+=1;
10717 }
10718
10719 /*
10720 if(s==1)
10721 {
10722 if((tile&3)==3)
10723 tile+=48;
10724 else
10725 ++tile;
10726 }
10727 if(s==-1)
10728 {
10729 if((tile&3)==0)
10730 tile-=48;
10731 else
10732 --tile;
10733 }
10734 }
10735 */
10736 bound(tile,0,255);
10737 tile += page;
10738
10739 if(!(key[KEY_LSHIFT] || key[KEY_RSHIFT]))
10740 tile2 = tile;
10741 }
10742
10743 void draw_combo_list_window()
10744 {
10745 int32_t window_xofs=0;
10746 int32_t window_yofs=0;
10747 int32_t w = 640;
10748 int32_t h = 480;
10749
10750 window_xofs=(zq_screen_w-w-12)>>1;
10751 window_yofs=(zq_screen_h-h-25-6)>>1;
10752 jwin_draw_win(screen, window_xofs, window_yofs, w+6+6, h+25+6, FR_WIN);
10753 jwin_draw_frame(screen, window_xofs+4, window_yofs+23, w+2+2, h+4+2-64, FR_DEEP);
10754 FONT *oldfont = font;
10755 font = get_zc_font(font_lfont);
10756 jwin_draw_titlebar(screen, window_xofs+3, window_yofs+3, w+6, 18, "Select Combo", true);
10757 font=oldfont;
10758 }
10759
10760
10761 static int32_t _selected_combo=-1, _selected_cset=-1;
10762 bool select_combo_2(int32_t &cmb,int32_t &cs)
10763 {
10764 popup_zqdialog_start();
10765 reset_combo_animations();
10766 reset_combo_animations2();
10767 combopage_animate = zc_get_config("ZQ_GUI","combopage_animate",1);
10768 // static int32_t cmb=0;
10769 int32_t page=cmb>>8;
10770 int32_t tile2=cmb;
10771 int32_t done=0;
10772 int32_t tile_clicked=-1;
10773 int32_t t2;
10774 int32_t copy=-1;
10775 int32_t copycnt=0;
10776
10777 position_mouse_z(0);
10778
10779 go();
10780 int32_t w = 640;
10781 int32_t h = 480;
10782 int32_t window_xofs=(zq_screen_w-w-12)>>1;
10783 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
10784 int32_t screen_xofs=window_xofs+6;
10785 int32_t screen_yofs=window_yofs+25;
10786 int32_t panel_yofs=3;
10787 int32_t mul = 2;
10788 FONT *tfont = get_zc_font(font_lfont_l);
10789
10790 draw_combo_list_window();
10791 draw_combos(page,cs,true);
10792 combo_info(cmb,tile2,cs,copy,copycnt,page,4);
10793
10794 while(gui_mouse_b())
10795 {
10796 /* do nothing */
10797 rest(1);
10798 }
10799
10800 bool bdown=false;
10801 int32_t f=0;
10802 int otl = cmb, otl2 = tile2;
10803
10804 do
10805 {
10806 HANDLE_CLOSE_ZQDLG();
10807 if(exiting_program) break;
10808 rest(4);
10809 bool redraw=false;
10810
10811 if(mouse_z<0)
10812 {
10813 if(page<COMBO_PAGES-1)
10814 {
10815 ++page;
10816 cmb=tile2=(page<<8)+(cmb&0xFF);
10817 }
10818
10819 position_mouse_z(0);
10820 redraw=true;
10821 }
10822 else if(mouse_z>0)
10823 {
10824 if(page>0)
10825 {
10826 --page;
10827 cmb=tile2=(page<<8)+(cmb&0xFF);
10828 }
10829
10830 position_mouse_z(0);
10831 redraw=true;
10832 }
10833
10834 if(keypressed())
10835 {
10836 switch(readkey()>>8)
10837 {
10838 case KEY_DEL:
10839 cmb=0;
10840 done=2;
10841 break;
10842
10843 case KEY_ENTER_PAD:
10844 case KEY_ENTER:
10845 done=2;
10846 break;
10847
10848 case KEY_ESC:
10849 done=1;
10850 break;
10851
10852 case KEY_F1:
10853 onHelp();
10854 break;
10855
10856 case KEY_EQUALS:
10857 case KEY_PLUS_PAD:
10858 cs = (cs<13) ? cs+1:0;
10859 redraw=true;
10860 break;
10861
10862 case KEY_MINUS:
10863 case KEY_MINUS_PAD:
10864 cs = (cs>0) ? cs-1:13;
10865 redraw=true;
10866 break;
10867
10868 case KEY_UP:
10869 sel_combo(cmb,tile2,-COMBOS_PER_ROW,true);
10870 redraw=true;
10871 break;
10872
10873 case KEY_DOWN:
10874 sel_combo(cmb,tile2,COMBOS_PER_ROW,true);
10875 redraw=true;
10876 break;
10877
10878 case KEY_LEFT:
10879 sel_combo(cmb,tile2,-1,true);
10880 redraw=true;
10881 break;
10882
10883 case KEY_RIGHT:
10884 sel_combo(cmb,tile2,1,true);
10885 redraw=true;
10886 break;
10887
10888 case KEY_PGUP:
10889 if(page>0)
10890 {
10891 --page;
10892 cmb=tile2=(page<<8)+(cmb&0xFF);
10893 }
10894
10895 redraw=true;
10896 break;
10897
10898 case KEY_PGDN:
10899 if(page<COMBO_PAGES-1)
10900 {
10901 ++page;
10902 cmb=tile2=(page<<8)+(cmb&0xFF);
10903 }
10904
10905 redraw=true;
10906 break;
10907
10908 case KEY_P:
10909 {
10910 int32_t choosepage=getnumber("Goto Page", (PreFillComboEditorPage?page:0));
10911
10912 if(!cancelgetnum)
10913 page=(zc_min(choosepage,COMBO_PAGES-1));
10914
10915 cmb=tile2=(page<<8)+(cmb&0xFF);
10916 redraw=true;
10917 break;
10918 }
10919 }
10920
10921 clear_keybuf();
10922 }
10923
10924 if(gui_mouse_b()&1)
10925 {
10926 if(isinRect(gui_mouse_x(),gui_mouse_y(),window_xofs + w + 12 - 21, window_yofs + 5, window_xofs + w +12 - 21 + 15, window_yofs + 5 + 13))
10927 {
10928 if(do_x_button(screen, w+12+window_xofs - 21, 5+window_yofs))
10929 {
10930 done=1;
10931 }
10932 }
10933
10934 int32_t x=gui_mouse_x()-screen_xofs;
10935 int32_t y=gui_mouse_y()-screen_yofs;
10936
10937 if(y>=0 && y<208*mul)
10938 {
10939 x=zc_min(zc_max(x,0),(320*mul)-1);
10940 int32_t t;
10941
10942 t = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
10943
10944 bound(t,0,255);
10945 t+=page<<8;
10946 cmb=tile2=t;
10947
10948 if(tile_clicked!=t)
10949 {
10950 dclick_status=DCLICK_NOT;
10951 }
10952 else if(dclick_status == DCLICK_AGAIN)
10953 {
10954 while(gui_mouse_b())
10955 {
10956 /* do nothing */
10957 }
10958
10959 t2 = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
10960
10961 if(t2!=t)
10962 {
10963 dclick_status=DCLICK_NOT;
10964 }
10965 else
10966 {
10967 done=2;
10968 }
10969 }
10970
10971 tile_clicked=t;
10972 }
10973 else if(y>=(208*mul) && x>(300*mul) && !bdown)
10974 {
10975 if(y<(224*mul)+panel_yofs && page>0)
10976 {
10977 --page;
10978 redraw=true;
10979 }
10980
10981 if(y>=(224*mul)+panel_yofs && page<COMBO_PAGES-1)
10982 {
10983 ++page;
10984 redraw=true;
10985 }
10986
10987 bdown=true;
10988 }
10989
10990 if(!bdown && isinRect(x,y,(247*mul),(213*mul),((247+44)*mul),((213+21)*mul)))
10991 {
10992 FONT *tf = font;
10993 font = tfont;
10994
10995 if(do_text_button((247*mul)+screen_xofs,(213*mul)+screen_yofs+panel_yofs,(44*mul),(21*mul),"Done"))
10996 {
10997 done=2;
10998 }
10999
11000 font = tf;
11001 }
11002 else if(!bdown && isinRect(x,y,320,440+panel_yofs,320+16,440+panel_yofs+16))
11003 {
11004 FONT *tf = font;
11005 font = tfont;
11006
11007 //do_scheckbox(screen2,320,440+panel_yofs,16,jwin_pal[jcTEXTBG],jwin_pal[jcTEXTFG],combopage_animate,screen_xofs,screen_yofs);
11008 combopage_animate = combopage_animate ? 0 : 1;
11009 zc_set_config("ZQ_GUI","combopage_animate",combopage_animate);
11010 redraw = true;
11011
11012 font = tf;
11013 }
11014
11015 bdown=true;
11016 }
11017
11018 bool r_click = false;
11019
11020 if(gui_mouse_b()&2 && !bdown)
11021 {
11022 int32_t x=gui_mouse_x()+screen_xofs;
11023 int32_t y=gui_mouse_y()+screen_yofs;
11024
11025 if(y>=0 && y<208*mul)
11026 {
11027 x=zc_min(zc_max(x,0),(320*mul)-1);
11028 int32_t t;
11029
11030 t = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
11031
11032 bound(t,0,255);
11033 t+=page<<8;
11034
11035 if(t<zc_min(cmb,tile2) || t>zc_max(cmb,tile2))
11036 cmb=tile2=t;
11037 }
11038
11039 bdown = r_click = true;
11040 f=8;
11041 }
11042
11043 if(gui_mouse_b()==0)
11044 bdown=false;
11045
11046 if((f%8) || InvalidBG == 1)
11047 redraw = true;
11048 if(otl != cmb || otl2 != tile2)
11049 {
11050 otl = cmb;
11051 otl2 = tile2;
11052 redraw = true;
11053 }
11054
11055 if(redraw || combopage_animate)
11056 draw_combos(page,cs,true);
11057
11058 combo_info(cmb,tile2,cs,copy,copycnt,page,4);
11059
11060 if(f&8)
11061 {
11062 int32_t x,y;
11063
11064 for(int32_t i=zc_min(cmb,tile2); i<=zc_max(cmb,tile2); i++)
11065 {
11066 if((i>>8)==page)
11067 {
11068 int32_t t=i&255;
11069
11070 x=((t&3) + ((t/52)<<2)) << 5;
11071 y=((t%52)>>2) << 5;
11072
11073 safe_rect(screen,x+screen_xofs,y+screen_yofs,x+screen_xofs+(16*mul)-1,y+screen_yofs+(16*mul)-1,vc(CmbPgCursorCol),2);
11074 }
11075 }
11076
11077 SCRFIX();
11078 }
11079
11080 ++f;
11081
11082 }
11083 while(!done);
11084
11085 while(gui_mouse_b())
11086 {
11087 /* do nothing */
11088 rest(1);
11089 }
11090
11091 comeback();
11092 setup_combo_animations();
11093 setup_combo_animations2();
11094
11095 bool ret = done==2;
11096 if(ret)
11097 {
11098 _selected_combo = cmb;
11099 _selected_cset = cs;
11100 }
11101
11102 popup_zqdialog_end();
11103 return ret;
11104 }
11105
11106 bool select_combo_3(int32_t &cmb,int32_t &cs)
11107 {
11108 if(_selected_combo < 0)
11109 {
11110 _selected_combo = Combo;
11111 _selected_cset = CSet;
11112 }
11113 cmb = _selected_combo;
11114 cs = _selected_cset;
11115 return select_combo_2(cmb,cs);
11116 }
11117
11118 bool advpaste(int32_t tile, int32_t tile2, int32_t copy)
11119 {
11120 static bitstring pasteflags;
11121 static const vector<CheckListInfo> advp_names =
11122 {
11123 { "Tile" },
11124 { "CSet2" },
11125 { "Solidity" },
11126 { "Animation" },
11127 { "Type" },
11128 { "Inherent Flag" },
11129 { "Attribytes" },
11130 { "Attrishorts" },
11131 { "Attributes" },
11132 { "Flags", "The 16 Flags on the 'Flags' tab" },
11133 { "Gen. Flags", "The 2 'General Flags' on the 'Flags' tab" },
11134 { "Label" },
11135 { "Script" },
11136 { "Effect" },
11137 { "Triggers Tab" },
11138 { "Lifting Tab" },
11139 { "Gen: Movespeed", "The Movespeed related values from the 'General' tab" },
11140 { "Gen: SFX", "The SFX related values from the 'General' tab" },
11141 { "Gen: Sprites", "The Sprites related values from the 'General' tab" },
11142 };
11143 if(!call_checklist_dialog("Advanced Paste",advp_names,pasteflags))
11144 return false;
11145
11146 //Paste to each combo in the range
11147 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); ++i)
11148 {
11149 combobuf[i].advpaste(combobuf[copy], pasteflags);
11150 }
11151
11152 if(pasteflags.get(CMB_ADVP_TILE)) //reset animations if needed
11153 {
11154 setup_combo_animations();
11155 setup_combo_animations2();
11156 }
11157
11158 return true;
11159 }
11160
11161 int32_t combo_screen(int32_t pg, int32_t tl)
11162 {
11163 popup_zqdialog_start();
11164 reset_combo_animations();
11165 reset_combo_animations2();
11166 combopage_animate = zc_get_config("ZQ_GUI","combopage_animate",1);
11167 static int32_t tile=0;
11168 static int32_t page=0;
11169
11170 if(pg>-1)
11171 page = pg;
11172
11173 if(tl>-1)
11174 tile = tl;
11175
11176 int32_t tile2=tile;
11177 int32_t done=0;
11178 int32_t cs = CSet;
11179 int32_t copy=-1;
11180 int32_t copycnt=0;
11181
11182 int32_t tile_clicked=-1;
11183 int32_t t2;
11184
11185 bool masscopy;
11186
11187 go();
11188 int32_t w = 640;
11189 int32_t h = 480;
11190 int32_t window_xofs=(zq_screen_w-w-12)>>1;
11191 int32_t window_yofs=(zq_screen_h-h-25-6)>>1;
11192 int32_t screen_xofs=window_xofs+6;
11193 int32_t screen_yofs=window_yofs+25;
11194 int32_t panel_yofs=3;
11195 int32_t mul = 2;
11196 FONT *tfont = get_zc_font(font_lfont_l);
11197
11198 draw_combo_list_window();
11199 draw_combos(page,cs,true);
11200 combo_info(tile,tile2,cs,copy,copycnt,page,6);
11201 go_combos();
11202 position_mouse_z(0);
11203
11204 while(gui_mouse_b())
11205 {
11206 /* do nothing */
11207 }
11208
11209 bool bdown=false;
11210 int32_t f=0;
11211 int otl = tile, otl2 = tile2;
11212
11213 do
11214 {
11215 HANDLE_CLOSE_ZQDLG();
11216 if(exiting_program) break;
11217 rest(4);
11218 bool redraw=false;
11219
11220 if(mouse_z<0)
11221 {
11222 if(page<COMBO_PAGES-1)
11223 {
11224 ++page;
11225 tile=tile2=(page<<8)+(tile&0xFF);
11226 }
11227
11228 position_mouse_z(0);
11229 redraw=true;
11230 }
11231 else if(mouse_z>0)
11232 {
11233 if(page>0)
11234 {
11235 --page;
11236 tile=tile2=(page<<8)+(tile&0xFF);
11237 }
11238
11239 position_mouse_z(0);
11240 redraw=true;
11241 }
11242
11243 if(keypressed())
11244 {
11245 switch(readkey()>>8)
11246 {
11247 case KEY_ENTER_PAD:
11248 case KEY_ENTER:
11249 done=2;
11250 break;
11251
11252 case KEY_ESC:
11253 done=1;
11254 break;
11255
11256 case KEY_F1:
11257 onHelp();
11258 break;
11259
11260 case KEY_EQUALS:
11261 case KEY_PLUS_PAD:
11262 if(CHECK_CTRL_CMD)
11263 {
11264 int32_t amnt = (key[KEY_LSHIFT] || key[KEY_RSHIFT]) ?
11265 ((key[KEY_ALT] || key[KEY_ALTGR]) ? TILES_PER_PAGE*10 : TILES_PER_ROW)
11266 : ((key[KEY_ALT] || key[KEY_ALTGR]) ? TILES_PER_PAGE : 1);
11267
11268 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); ++i)
11269 {
11270 combobuf[i].set_tile(wrap(combobuf[i].o_tile + amnt,
11271 0, NEWMAXTILES-1));
11272 }
11273
11274 setup_combo_animations();
11275 redraw=true;
11276 }
11277 else
11278 {
11279 cs = (cs<13) ? cs+1:0;
11280 redraw=true;
11281 }
11282
11283 break;
11284
11285 case KEY_MINUS:
11286 case KEY_MINUS_PAD:
11287 if(CHECK_CTRL_CMD)
11288 {
11289 int32_t amnt = (key[KEY_LSHIFT] || key[KEY_RSHIFT]) ?
11290 ((key[KEY_ALT] || key[KEY_ALTGR]) ? TILES_PER_PAGE*10 : TILES_PER_ROW)
11291 : ((key[KEY_ALT] || key[KEY_ALTGR]) ? TILES_PER_PAGE : 1);
11292
11293 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); ++i)
11294 {
11295 combobuf[i].set_tile(wrap(combobuf[i].o_tile - amnt,
11296 0, NEWMAXTILES-1));
11297 }
11298
11299 setup_combo_animations();
11300 redraw=true;
11301 }
11302 else
11303 {
11304 cs = (cs>0) ? cs-1:13;
11305 redraw=true;
11306 }
11307
11308 break;
11309
11310 case KEY_UP:
11311 sel_combo(tile,tile2,-COMBOS_PER_ROW,true);
11312 redraw=true;
11313 break;
11314
11315 case KEY_DOWN:
11316 sel_combo(tile,tile2,COMBOS_PER_ROW,true);
11317 redraw=true;
11318 break;
11319
11320 case KEY_LEFT:
11321 sel_combo(tile,tile2,-1,true);
11322 redraw=true;
11323 break;
11324
11325 case KEY_RIGHT:
11326 sel_combo(tile,tile2,1,true);
11327 redraw=true;
11328 break;
11329
11330 case KEY_PGUP:
11331 if(page>0)
11332 {
11333 --page;
11334 tile=tile2=(page<<8)+(tile&0xFF);
11335 }
11336
11337 redraw=true;
11338 break;
11339
11340 case KEY_PGDN:
11341 if(page<COMBO_PAGES-1)
11342 {
11343 ++page;
11344 tile=tile2=(page<<8)+(tile&0xFF);
11345 }
11346
11347 redraw=true;
11348 break;
11349
11350 case KEY_A:
11351 {
11352 tile=(page<<8);
11353 tile2=(page<<8)+(0xFF);
11354 }
11355
11356 redraw=true;
11357 break;
11358
11359 case KEY_P:
11360 {
11361 int32_t choosepage = getnumber("Goto Page", (PreFillComboEditorPage?page:0));
11362
11363 if(!cancelgetnum)
11364 page=(zc_min(choosepage,COMBO_PAGES-1));
11365
11366 tile=tile2=(page<<8)+(tile&0xFF);
11367 redraw=true;
11368 }
11369 break;
11370
11371 case KEY_U:
11372 comeback_combos();
11373 redraw=true;
11374 break;
11375
11376 case KEY_E:
11377 go_combos();
11378 edit_combo(tile,false,cs);
11379 redraw=true;
11380 setup_combo_animations();
11381 setup_combo_animations2();
11382 break;
11383
11384 case KEY_C:
11385 go_combos();
11386 copy=zc_min(tile,tile2);
11387 copycnt=abs(tile-tile2)+1;
11388 redraw=true;
11389 break;
11390
11391 case KEY_H:
11392 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11393 {
11394 combobuf[i].flip^=1;
11395 byte w2=combobuf[i].walk;
11396 combobuf[i].walk=((w2& ~0x33)>>2 | (w2&0x33)<<2);
11397 w2=combobuf[i].csets;
11398 combobuf[i].csets= (((w2& ~0x50)>>1 | (w2&0x50)<<1) & ~0x0F) | (w2 & 0x0F);
11399 }
11400
11401 redraw=true;
11402 saved=false;
11403 break;
11404
11405 case KEY_M:
11406 if((copy!=-1)&&(copy!=zc_min(tile,tile2)))
11407 {
11408 move_combos(tile,tile2,copy,copycnt);
11409 saved=false;
11410 }
11411
11412 redraw=true;
11413 break;
11414
11415 case KEY_S:
11416 tile=tile2=zc_min(tile,tile2);
11417
11418 if(copy>=0 && tile!=copy)
11419 {
11420 go_combos();
11421
11422 for(int32_t i=0; i<copycnt; i++)
11423 {
11424 zc_swap(combobuf[copy+i],combobuf[tile+i]);
11425 }
11426
11427 saved=false;
11428 setup_combo_animations();
11429 setup_combo_animations2();
11430 }
11431
11432 redraw=true;
11433 copy=-1;
11434 break;
11435
11436 case KEY_V:
11437 if((CHECK_CTRL_CMD) && copy != -1)
11438 {
11439 if(advpaste(tile, tile2, copy))
11440 {
11441 saved=false;
11442 redraw=true;
11443 copy=-1;
11444 }
11445
11446 break;
11447 }
11448
11449 masscopy=(key[KEY_LSHIFT] || key[KEY_RSHIFT])?1:0;
11450
11451 if(copy==-1)
11452 {
11453 go_combos();
11454
11455 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11456 {
11457 combobuf[i].flip^=2;
11458 byte w2=combobuf[i].walk;
11459 combobuf[i].walk=(w2&0x55)<<1 | (w2& ~0x55)>>1;
11460 w2=combobuf[i].csets;
11461 combobuf[i].csets= (((w2&0x30)<<2 | (w2& ~0x30)>>2) & ~0x0F) | (w2 & 0x0F);
11462 }
11463
11464 saved=false;
11465 }
11466 else
11467 {
11468 go_combos();
11469 copy_combos(tile,tile2,copy,copycnt,masscopy);
11470 setup_combo_animations();
11471 setup_combo_animations2();
11472 saved=false;
11473 }
11474
11475 redraw=true;
11476 break;
11477 case KEY_R:
11478 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11479 {
11480 combobuf[i].flip = rotate_value(combobuf[i].flip);
11481 combobuf[i].walk = rotate_walk(combobuf[i].walk);
11482 combobuf[i].csets = rotate_cset(combobuf[i].csets);
11483 }
11484
11485 redraw=true;
11486 saved=false;
11487 break;
11488
11489 case KEY_I:
11490 {
11491 // rev.1509; Can now insert/remove all selected combos
11492 int32_t z=tile;
11493 int32_t numSelected = abs(tile-tile2) + 1;
11494 tile=zc_min(tile,tile2);
11495 tile2=MAXCOMBOS;
11496 copy = tile + numSelected; // copy=tile+1;
11497 copycnt = MAXCOMBOS-tile-numSelected; // copycnt=MAXCOMBOS-tile;
11498
11499 if(key[KEY_LSHIFT]||key[KEY_RSHIFT])
11500 {
11501 char buf[64];
11502
11503 if(numSelected>1)
11504 sprintf(buf,"Remove combos %d - %d?",tile, copy-1);
11505 else
11506 sprintf(buf,"Remove combo %d?",tile);
11507
11508 if(jwin_alert("Confirm Remove",buf,"This will offset all of the combos that follow!",NULL,"&Yes","&No",'y','n',get_zc_font(font_lfont))==1)
11509 {
11510 move_combos(tile,tile2,copy, copycnt);
11511 //don't allow the user to undo; quest combo references are incorrect -DD
11512 go_combos();
11513 redraw=true;
11514 saved=false;
11515 }
11516 }
11517 else
11518 {
11519 char buf[64];
11520
11521 if(numSelected>1)
11522 sprintf(buf,"Insert %d blank combos?",numSelected);
11523 else
11524 sprintf(buf,"Insert a blank combo?");
11525
11526 if(jwin_alert("Confirm Insert",buf,"This will offset all of the combos that follow!",NULL,"&Yes","&No",'y','n',get_zc_font(font_lfont))==1)
11527 {
11528 move_combos(copy,tile2,tile, copycnt);
11529 go_combos();
11530 redraw=true;
11531 saved=false;
11532 }
11533 }
11534
11535 copy=-1;
11536 tile2=tile=z;
11537 }
11538 break;
11539
11540 case KEY_DEL:
11541 {
11542 char buf[40];
11543
11544 if(tile==tile2)
11545 {
11546 sprintf(buf,"Delete combo %d?",tile);
11547 }
11548 else
11549 {
11550 sprintf(buf,"Delete combos %d-%d?",zc_min(tile,tile2),zc_max(tile,tile2));
11551 }
11552
11553 if(jwin_alert("Confirm Delete",buf,NULL,NULL,"&Yes","&No",'y','n',get_zc_font(font_lfont))==1)
11554 {
11555 go_combos();
11556
11557 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11558 {
11559 clear_combo(i);
11560 }
11561
11562 tile=tile2=zc_min(tile,tile2);
11563 redraw=true;
11564 saved=false;
11565 setup_combo_animations();
11566 setup_combo_animations2();
11567 }
11568 }
11569 break;
11570 }
11571
11572 clear_keybuf();
11573 }
11574
11575 if(gui_mouse_b()&1)
11576 {
11577 if(isinRect(gui_mouse_x(),gui_mouse_y(),window_xofs + w + 12 - 21, window_yofs + 5, window_xofs + w +12 - 21 + 15, window_yofs + 5 + 13))
11578 {
11579 if(do_x_button(screen, w+12+window_xofs - 21, 5+window_yofs))
11580 {
11581 done=1;
11582 }
11583 }
11584
11585 int32_t x=gui_mouse_x()-screen_xofs;
11586 int32_t y=gui_mouse_y()-screen_yofs;
11587
11588 if(y>=0 && y<(208*mul))
11589 {
11590 x=zc_min(zc_max(x,0),(320*mul)-1);
11591 int32_t t;
11592
11593 t = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
11594
11595 bound(t,0,255);
11596 t+=page<<8;
11597
11598 if(key[KEY_LSHIFT] || key[KEY_RSHIFT])
11599 {
11600 tile2=t;
11601 }
11602 else
11603 {
11604 tile=tile2=t;
11605 }
11606
11607 if(tile_clicked!=t)
11608 {
11609 dclick_status=DCLICK_NOT;
11610 }
11611 else if(dclick_status == DCLICK_AGAIN)
11612 {
11613 while(gui_mouse_b())
11614 {
11615 /* do nothing */
11616 rest(1);
11617 }
11618
11619 t2 = ((x>>6)*52) + ((x>>4)&3) + ((y>>4)<<2);
11620
11621 bound(t2,0,255);
11622 t2+=page<<8;
11623
11624 if(t2!=t)
11625 {
11626 dclick_status=DCLICK_NOT;
11627 }
11628 else
11629 {
11630 go_combos();
11631 edit_combo(tile,false,cs);
11632 redraw=true;
11633 setup_combo_animations();
11634 setup_combo_animations2();
11635 }
11636 }
11637
11638 tile_clicked=t;
11639 }
11640 else if(x>(300*mul) && !bdown)
11641 {
11642 if(y<(224*mul)+panel_yofs && page>0)
11643 {
11644 --page;
11645 redraw=true;
11646 }
11647
11648 if(y>=(224*mul)+panel_yofs && page<COMBO_PAGES-1)
11649 {
11650 ++page;
11651 redraw=true;
11652 }
11653
11654 bdown=true;
11655 }
11656
11657 if(!bdown && isinRect(x,y,(202*mul),(213*mul)+panel_yofs,(202+44)*mul,(213+21)*mul))
11658 {
11659 FONT *tf = font;
11660 font = tfont;
11661
11662 if(do_text_button((202*mul)+screen_xofs,(213*mul)+screen_yofs+panel_yofs,(44*mul),(21*mul),"Edit"))
11663 {
11664 font = tf;
11665 edit_combo(tile,false,cs);
11666 redraw=true;
11667 }
11668
11669 font = tf;
11670 }
11671 else if(!bdown && isinRect(x,y,(247*mul),(213*mul)+panel_yofs,(247+44)*mul,(213+21)*mul))
11672 {
11673 FONT *tf = font;
11674 font = tfont;
11675
11676 if(do_text_button((247*mul)+screen_xofs,(213*mul)+screen_yofs+panel_yofs,(44*mul),(21*mul),"Done"))
11677 {
11678 done=1;
11679 }
11680
11681 font = tf;
11682 }
11683 else if(!bdown && isinRect(x,y,320,440+panel_yofs,320+16,440+panel_yofs+16))
11684 {
11685 FONT *tf = font;
11686 font = tfont;
11687
11688 //do_scheckbox(screen2,320,440+panel_yofs,16,jwin_pal[jcTEXTBG],jwin_pal[jcTEXTFG],combopage_animate,screen_xofs,screen_yofs);
11689 combopage_animate = combopage_animate ? 0 : 1;
11690 zc_set_config("ZQ_GUI","combopage_animate",combopage_animate);
11691 redraw = true;
11692
11693 font = tf;
11694 }
11695
11696 bdown=true;
11697 }
11698
11699 bool r_click = false;
11700
11701 if(gui_mouse_b()&2 && !bdown)
11702 {
11703 int32_t x=gui_mouse_x()-screen_xofs;
11704 int32_t y=gui_mouse_y()-screen_yofs;
11705
11706 if(y>=0 && y<(208*mul))
11707 {
11708 x=zc_min(zc_max(x,0),(320*mul)-1);
11709 int32_t t;
11710
11711 t = ((x>>7)*52) + ((x>>5)&3) + ((y>>5)<<2);
11712
11713 bound(t,0,255);
11714 t+=page<<8;
11715
11716 if(t<zc_min(tile,tile2) || t>zc_max(tile,tile2))
11717 {
11718 tile=tile2=t;
11719 }
11720 }
11721
11722 bdown = r_click = true;
11723 f=8;
11724 }
11725
11726 REDRAW:
11727
11728 if(gui_mouse_b()==0)
11729 bdown=false;
11730
11731 if((f%8) || InvalidBG == 1)
11732 redraw = true;
11733 if(otl != tile || otl2 != tile2)
11734 {
11735 otl = tile;
11736 otl2 = tile2;
11737 redraw = true;
11738 }
11739
11740 if(redraw || combopage_animate)
11741 draw_combos(page,cs,true);
11742
11743 combo_info(tile,tile2,cs,copy,copycnt,page,6);
11744
11745 if(f&8)
11746 {
11747 int32_t x,y;
11748
11749 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11750 {
11751 if((i>>8)==page)
11752 {
11753 int32_t t=i&255;
11754
11755 x=((t&3) + ((t/52)<<2)) << 5;
11756 y=((t%52)>>2) << 5;
11757
11758 safe_rect(screen,x+screen_xofs,y+screen_yofs,x+screen_xofs+(16*mul)-1,y+screen_yofs+(16*mul)-1,vc(CmbPgCursorCol),2);
11759 }
11760 }
11761
11762 SCRFIX();
11763 }
11764
11765 ++f;
11766
11767 //Seriously? There is duplicate code for the r-click menu? -Gleeok
11768 if(r_click)
11769 {
11770 NewMenu rcmenu
11771 {
11772 { "Copy", [&]()
11773 {
11774 go_combos();
11775 copy=zc_min(tile,tile2);
11776 copycnt=abs(tile-tile2)+1;
11777 } },
11778 { "Paste", [&]()
11779 {
11780 if((CHECK_CTRL_CMD) && copy != -1)
11781 {
11782 if(advpaste(tile, tile2, copy))
11783 {
11784 saved=false;
11785 redraw=true;
11786 copy=-1;
11787 }
11788 return;
11789 }
11790
11791 masscopy=(key[KEY_LSHIFT] || key[KEY_RSHIFT])?1:0;
11792
11793 if(copy>-1)
11794 {
11795 go_combos();
11796 copy_combos(tile,tile2,copy,copycnt,masscopy);
11797 setup_combo_animations();
11798 setup_combo_animations2();
11799 saved=false;
11800 }
11801 } },
11802 { "Adv. Paste", [&]()
11803 {
11804 if(copy > -1)
11805 {
11806 if(advpaste(tile, tile2, copy))
11807 {
11808 saved=false;
11809 redraw=true;
11810 copy=-1;
11811 }
11812 }
11813 } },
11814 { "Swap", [&]()
11815 {
11816 tile=tile2=zc_min(tile,tile2);
11817
11818 if(copy>=0 && tile!=copy)
11819 {
11820 go_combos();
11821
11822 for(int32_t i=0; i<copycnt; i++)
11823 {
11824 zc_swap(combobuf[copy+i],combobuf[tile+i]);
11825 }
11826
11827 saved=false;
11828 setup_combo_animations();
11829 setup_combo_animations2();
11830 }
11831 copy=-1;
11832 } },
11833 { "Delete", [&]()
11834 {
11835 string msg;
11836
11837 if(tile==tile2)
11838 msg = fmt::format("Delete combo {}?",tile);
11839 else
11840 msg = fmt::format("Delete combos {}-{}?",zc_min(tile,tile2),zc_max(tile,tile2));
11841 bool didconfirm = false;
11842 AlertDialog("Confirm Delete",msg,
11843 [&](bool ret,bool)
11844 {
11845 if(ret)
11846 didconfirm = true;
11847 }).show();
11848 if(didconfirm)
11849 {
11850 go_combos();
11851
11852 for(int32_t i=zc_min(tile,tile2); i<=zc_max(tile,tile2); i++)
11853 clear_combo(i);
11854
11855 tile=tile2=zc_min(tile,tile2);
11856 saved=false;
11857 }
11858 } },
11859 {},
11860 { "Edit", [&]()
11861 {
11862 go_combos();
11863 edit_combo(tile,false,cs);
11864 } },
11865 { "Insert", [&]()
11866 {
11867 int z = tile;
11868 int count = abs(tile-tile2)+1;
11869 tile = zc_min(tile,tile2);
11870 tile2 = MAXCOMBOS;
11871 copy = tile+count;
11872 copycnt = MAXCOMBOS-tile-count;
11873
11874 string msg;
11875
11876 if(count>1)
11877 msg = fmt::format("Insert combos {} - {}?"
11878 " This will offset all of the combos that follow!",tile, copy-1);
11879 else
11880 msg = fmt::format("Insert combo {}?"
11881 " This will offset all of the combos that follow!",tile);
11882
11883 bool didconfirm = false;
11884 AlertDialog("Confirm Insert",msg,
11885 [&](bool ret,bool)
11886 {
11887 if(ret)
11888 didconfirm = true;
11889 }).show();
11890 if(didconfirm)
11891 move_combos(copy, tile2, tile, copycnt);
11892 else return;
11893
11894 copy = -1;
11895 tile2 = tile = z;
11896
11897 //don't allow the user to undo; quest combo references are incorrect -DD
11898 go_combos();
11899 saved = false;
11900 } },
11901 { "Remove", [&]()
11902 {
11903 int z = tile;
11904 int count = abs(tile-tile2)+1;
11905 tile = zc_min(tile,tile2);
11906 tile2 = MAXCOMBOS;
11907 copy = tile+count;
11908 copycnt = MAXCOMBOS-tile-count;
11909
11910 string msg;
11911
11912 if(count>1)
11913 msg = fmt::format("Remove combos {} - {}?"
11914 " This will offset all of the combos that follow!",tile, copy-1);
11915 else
11916 msg = fmt::format("Remove combo {}?"
11917 " This will offset all of the combos that follow!",tile);
11918
11919 bool didconfirm = false;
11920 AlertDialog("Confirm Remove",msg,
11921 [&](bool ret,bool)
11922 {
11923 if(ret)
11924 didconfirm = true;
11925 }).show();
11926 if(didconfirm)
11927 move_combos(tile, tile2, copy, copycnt);
11928 else return;
11929
11930 copy = -1;
11931 tile2 = tile = z;
11932
11933 //don't allow the user to undo; quest combo references are incorrect -DD
11934 go_combos();
11935 saved = false;
11936 } },
11937 {},
11938 { "Locations", [&]()
11939 {
11940 int32_t z = Combo;
11941 Combo = tile;
11942 onComboLocationReport();
11943 Combo = z;
11944 } },
11945 };
11946 rcmenu.pop(window_mouse_x(),window_mouse_y());
11947 redraw = true;
11948 r_click = false;
11949 goto REDRAW;
11950 }
11951
11952 }
11953 while(!done);
11954
11955 while(gui_mouse_b())
11956 rest(1);
11957 comeback();
11958 setup_combo_animations();
11959 setup_combo_animations2();
11960 _selected_combo = tile;
11961 _selected_cset = cs;
11962 popup_zqdialog_end();
11963 return done-1;
11964 }
11965
11966 int32_t onCombos()
11967 {
11968 // reset_combo_animations();
11969 combo_screen(-1,-1);
11970 // setup_combo_animations();
11971 refresh(rALL);
11972 return D_O_K;
11973 }
11974
11975 int32_t d_ctile_proc(int32_t msg,DIALOG *d,int32_t c)
11976 {
11977 //these are here to bypass compiler warnings about unused arguments
11978 d=d;
11979 c=c;
11980
11981 if(msg==MSG_CLICK)
11982 {
11983 int32_t t=curr_combo.o_tile;
11984 int32_t f=curr_combo.flip;
11985
11986 if(select_tile(t,f,1,CSet,true,0,true))
11987 {
11988 curr_combo.tile=t;
11989 curr_combo.o_tile=t;
11990 curr_combo.flip=f;
11991 return D_REDRAW;
11992 }
11993 }
11994
11995 return D_O_K;
11996 }
11997
11998 int32_t d_combo_loader(int32_t msg,DIALOG *d,int32_t c)
11999 {
12000 //these are here to bypass compiler warnings about unused arguments
12001 c=c;
12002
12003 if(msg==MSG_DRAW)
12004 {
12005 FONT *f = get_zc_font(font_lfont_l);
12006 textprintf_ex(screen,f,d->x,d->y,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Tile:");
12007 textprintf_ex(screen,f,d->x+((1.5)*36),d->y,jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",curr_combo.o_tile);
12008 textprintf_ex(screen,f,d->x,d->y+(14),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"Flip:");
12009 textprintf_ex(screen,f,d->x+((1.5)*36),d->y+(14),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"%d",curr_combo.flip);
12010 textprintf_ex(screen,f,d->x,d->y+(36),jwin_pal[jcBOXFG],jwin_pal[jcBOX],"CSet2:");
12011 }
12012
12013 return D_O_K;
12014 }
12015
12016 int32_t click_d_ctile_proc()
12017 {
12018 d_ctile_proc(MSG_CLICK,NULL,0);
12019 return D_REDRAW;
12020 }
12021
12022 int32_t click_d_combo_proc();
12023
12024 const char *comboscriptdroplist(int32_t index, int32_t *list_size)
12025 {
12026 if(index<0)
12027 {
12028 *list_size = bidcomboscripts_cnt;
12029 return NULL;
12030 }
12031
12032 return bidcomboscripts[index].first.c_str();
12033 }
12034 9 ListData comboscript_list(comboscriptdroplist, &font);
12035
12036 bool call_combo_editor(int32_t);
12037 bool edit_combo(int32_t c,bool freshen,int32_t cs)
12038 {
12039 FONT* ofont = font;
12040 //CSet = cs;
12041 reset_combo_animations();
12042 reset_combo_animations2();
12043 bool edited = call_combo_editor(c);
12044 font = ofont;
12045
12046 if(freshen)
12047 {
12048 refresh(rALL);
12049 }
12050
12051 setup_combo_animations();
12052 setup_combo_animations2();
12053
12054 return edited;
12055 }
12056
12057 int32_t d_itile_proc(int32_t msg,DIALOG *d,int32_t)
12058 {
12059 switch(msg)
12060 {
12061 case MSG_CLICK:
12062 {
12063 int32_t cs = d->d2;
12064 int32_t f = 0;
12065
12066 if(select_tile(d->d1,f,1,cs,true))
12067 {
12068 int32_t ok=1;
12069
12070 if(newtilebuf[d->d1].format==tf8Bit)
12071 jwin_alert("Warning",
12072 "You have selected an 8-bit tile.",
12073 "It will not be drawn correctly",
12074 "on the file select screen.",
12075 "&OK",NULL,'o',0,get_zc_font(font_lfont));
12076
12077 return D_REDRAW;
12078 }
12079 }
12080 break;
12081
12082 case MSG_DRAW:
12083 d->w = 32+4;
12084 d->h = 32+4;
12085
12086 BITMAP *buf = create_bitmap_ex(8,16,16);
12087 BITMAP *bigbmp = create_bitmap_ex(8,d->w,d->h);
12088
12089 if(buf && bigbmp)
12090 {
12091 clear_bitmap(buf);
12092 overtile16(buf,d->d1,0,0,d->fg,0);
12093 stretch_blit(buf, bigbmp, 0,0, 16, 16, 2, 2, d->w-4, d->h-4);
12094 destroy_bitmap(buf);
12095 jwin_draw_frame(bigbmp,0, 0, d->w,d->h, FR_DEEP);
12096 blit(bigbmp,screen,0,0,d->x-1,d->y-1,d->w,d->h);
12097 destroy_bitmap(bigbmp);
12098 }
12099
12100 break;
12101 }
12102
12103 return D_O_K;
12104 }
12105
12106 static DIALOG icon_dlg[] =
12107 {
12108 /* (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp) */
12109 { jwin_win_proc, 70, 70, 170, 104, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Game Icons", NULL, NULL },
12110 { d_timer_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL },
12111 { d_itile_proc, 108+3, 112, 20, 20, 0, 0, 0, 0, 0, 6, NULL, NULL, NULL },
12112 { d_itile_proc, 138+3, 112, 20, 20, 0, 0, 0, 0, 0, 7, NULL, NULL, NULL },
12113 { d_itile_proc, 168+3, 112, 20, 20, 0, 0, 0, 0, 0, 8, NULL, NULL, NULL },
12114 { d_itile_proc, 198+3, 112, 20, 20, 0, 0, 0, 0, 0, 9, NULL, NULL, NULL },
12115 { jwin_button_proc, 90, 145, 61, 21, vc(14), vc(1), 13, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
12116 { jwin_button_proc, 170, 145, 61, 21, vc(14), vc(1), 27, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
12117 { jwin_text_proc, 108+11, 98, 8, 9, 0, 0, 0, 0, 0, 0, (void *) "0", NULL, NULL },
12118 { jwin_text_proc, 138+11, 98, 8, 9, 0, 0, 0, 0, 0, 0, (void *) "1", NULL, NULL },
12119 { jwin_text_proc, 168+11, 98, 8, 9, 0, 0, 0, 0, 0, 0, (void *) "2", NULL, NULL },
12120 { jwin_text_proc, 198+11, 98, 8, 9, 0, 0, 0, 0, 0, 0, (void *) "3+", NULL, NULL },
12121 { jwin_text_proc, 88, 98, 12, 9, 0, 0, 0, 0, 0, 0, (void *) "Ring:", NULL, NULL },
12122 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
12123 };
12124
12125 int32_t onIcons()
12126 {
12127 PALETTE pal;
12128 // pal = RAMpal;
12129 memcpy(pal,RAMpal,sizeof(RAMpal));
12130 icon_dlg[0].dp2=get_zc_font(font_lfont);
12131
12132 for(int32_t i=0; i<4; i++)
12133 {
12134 icon_dlg[i+2].d1 = QMisc.icons[i];
12135 icon_dlg[i+2].fg = i+6;
12136 load_cset(pal, i+6, pSprite(i+spICON1));
12137 }
12138
12139 zc_set_palette(pal);
12140
12141 large_dialog(icon_dlg);
12142
12143 int32_t ret = do_zqdialog(icon_dlg,7);
12144
12145 if(ret==6)
12146 {
12147 for(int32_t i=0; i<4; i++)
12148 {
12149 if(QMisc.icons[i] != icon_dlg[i+2].d1)
12150 {
12151 QMisc.icons[i] = icon_dlg[i+2].d1;
12152 saved=false;
12153 }
12154 }
12155 }
12156
12157 zc_set_palette(RAMpal);
12158 return D_O_K;
12159 }
12160
12161 // Identical to jwin_frame_proc, but is treated differently by large_dialog()
12162 int32_t d_comboframe_proc(int32_t msg, DIALOG *d, int32_t)
12163 {
12164 if(msg == MSG_DRAW)
12165 {
12166 jwin_draw_frame(screen, d->x, d->y, d->w, d->h, d->d1);
12167 }
12168
12169 return D_O_K;
12170 }
12171
12172 int32_t d_combo_proc(int32_t msg,DIALOG *d,int32_t)
12173 {
12174 switch(msg)
12175 {
12176 case MSG_CLICK:
12177 {
12178 if((d->flags&D_NOCLICK))
12179 break;
12180
12181 int32_t ret = (d->flags & D_EXIT) ? D_CLOSE : D_O_K;
12182 int32_t combo2;
12183 int32_t cs;
12184
12185 if(CHECK_ALT) //place selected cmb/cs
12186 {
12187 if(gui_mouse_b()&1)
12188 {
12189 if(!CHECK_SHIFT)
12190 d->d1 = Combo;
12191 d->fg = CSet;
12192 }
12193
12194 return ret|D_REDRAW;
12195 }
12196 else if(gui_mouse_b()&2||nextcombo_fake_click==2) //clear to 0/0
12197 {
12198 d->d1=0;
12199 d->fg=0;
12200 return ret|D_REDRAW;
12201 }
12202 else if(gui_mouse_b()&1||nextcombo_fake_click==1) //popup combo picker
12203 {
12204 combo2=d->d1;
12205 cs=d->fg;
12206
12207 if((CHECK_CTRL_CMD ? select_combo_3 : select_combo_2)(combo2, cs))
12208 {
12209 d->d1=combo2;
12210 d->fg=cs;
12211 }
12212
12213 return ret|D_REDRAW;
12214 }
12215 else return ret|D_REDRAWME;
12216 }
12217 break;
12218
12219 case MSG_DRAW:
12220 {
12221 d->w = 32;
12222 d->h = 32;
12223
12224 BITMAP *buf = create_bitmap_ex(8,16,16);
12225 BITMAP *bigbmp = create_bitmap_ex(8,d->w,d->h);
12226
12227 if(buf && bigbmp)
12228 {
12229 clear_bitmap(buf);
12230
12231 if(d->d1==-1) // Display curr_combo instead of combobuf
12232 {
12233 newcombo hold = combobuf[0];
12234 combobuf[0] = curr_combo;
12235 putcombo(buf,0,0,0,d->fg);
12236 combobuf[0] = hold;
12237 }
12238 else if(d->d1)
12239 {
12240 putcombo(buf,0,0,d->d1,d->fg);
12241 }
12242
12243 stretch_blit(buf, bigbmp, 0,0, 16, 16, 0, 0, d->w, d->h);
12244 destroy_bitmap(buf);
12245 blit(bigbmp,screen,0,0,d->x-1,d->y-1,d->w,d->h);
12246 destroy_bitmap(bigbmp);
12247 }
12248 }
12249 break;
12250 }
12251 return D_O_K;
12252 }
12253
12254 // Hey, let's have a few hundred more lines of code, why not.
12255
12256 #define MR_4BIT 0
12257 #define MR_8BIT 1
12258
12259 static byte massRecolorSrc4Bit[16]={ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
12260 static byte massRecolorDest4Bit[16]={ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
12261 static word massRecolor8BitCSets=0; // Which CSets are affected? One bit each.
12262
12263 static byte massRecolorSrc8Bit[16]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
12264 static byte massRecolorDest8Bit[16]={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
12265
12266 static int32_t massRecolorDraggedColor=-1;
12267 static int32_t massRecolorCSet;
12268 static bool massRecolorIgnoreBlank=true;
12269 static byte massRecolorType=MR_4BIT;
12270
12271 // Shows the sets of colors to replace from/to.
12272 // D_CSET: Colors are 0-15 within the current CSet rather than absolute.
12273 // D_SETTABLE: Colors can be dragged and dropped onto this one.
12274 #define D_CSET D_USER
12275 #define D_SETTABLE (D_USER<<1)
12276 int32_t d_mr_cset_proc(int32_t msg, DIALOG* d, int32_t)
12277 {
12278 BITMAP* bmp=screen;
12279 int32_t colorWidth=(d->w-4)/16;
12280 byte* colors=static_cast<byte*>(d->dp);
12281
12282 switch(msg)
12283 {
12284 case MSG_DRAW:
12285 {
12286 jwin_draw_frame(bmp, d->x, d->y, d->w, d->h, FR_DEEP);
12287
12288 int32_t baseColor=((d->flags&D_CSET)!=0) ? massRecolorCSet*16 : 0;
12289 for(int32_t c=0; c<16; c++)
12290 {
12291 rectfill(bmp,
12292 d->x+2+c*colorWidth, d->y+2,
12293 d->x+2+((c+1)*colorWidth)-1, d->y+2+d->h-5,
12294 baseColor+colors[c]);
12295 }
12296 }
12297 break;
12298
12299 case MSG_LPRESS:
12300 {
12301 int32_t x=(gui_mouse_x()-(d->x+2))/colorWidth;
12302
12303 if(x >= 0 && x < 16) //sanity check!
12304 {
12305 massRecolorDraggedColor=colors[x];
12306 }
12307 }
12308 break;
12309
12310 case MSG_LRELEASE: // This isn't exactly right, but it'll do...
12311 if((d->flags&D_SETTABLE)!=0 && massRecolorDraggedColor>=0)
12312 {
12313 int32_t x=(gui_mouse_x()-(d->x+2))/colorWidth;
12314 if(x >= 0 && x < 16) //sanity check!
12315 {
12316 colors[x]=massRecolorDraggedColor;
12317 d->flags|=D_DIRTY;
12318 }
12319 }
12320 massRecolorDraggedColor=-1;
12321 break;
12322 }
12323
12324 return D_O_K;
12325 }
12326
12327 // Used for the full palette in 8-bit mode.
12328 static int32_t d_mr_palette_proc(int32_t msg, DIALOG* d, int32_t)
12329 {
12330 BITMAP* bmp=screen;
12331 int colorWidth=(d->w-4)/16;
12332 d->h = 4+(colorWidth*14);
12333 int colorHeight=colorWidth;
12334
12335 switch(msg)
12336 {
12337 case MSG_DRAW:
12338 {
12339 jwin_draw_frame(bmp, d->x, d->y, d->w, d->h, FR_DEEP);
12340 for(int cset=0; cset<=13; cset++)
12341 {
12342 for(int color=0; color<16; color++)
12343 {
12344 rectfill(bmp,
12345 d->x+2+color*colorWidth,
12346 d->y+2+cset*colorHeight,
12347 d->x+2+((color+1)*colorWidth)-1,
12348 d->y+2+((cset+1)*colorHeight)-1,
12349 cset*16+color);
12350 }
12351 }
12352 }
12353 break;
12354
12355 case MSG_LPRESS:
12356 {
12357 int cset=(gui_mouse_y()-(d->y+2))/colorHeight;
12358 int color=(gui_mouse_x()-(d->x+2))/colorWidth;
12359 massRecolorDraggedColor=cset*16+color;
12360 }
12361 break;
12362 }
12363
12364 return D_O_K;
12365 }
12366
12367 static DIALOG recolor_4bit_dlg[] =
12368 {
12369 // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp)
12370 { jwin_win_proc, 0, 0, 216, 224, 0, 0, 0, D_EXIT, 0, 0, (void *) "Recolor setup", NULL, NULL },
12371
12372 // 1
12373 { jwin_text_proc, 12, 32, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "From", NULL, NULL },
12374 { d_mr_cset_proc, 10, 42, 196, 16, 0, 0, 0, D_CSET, 0, 0, (void *)massRecolorSrc4Bit, NULL, NULL },
12375 { jwin_text_proc, 12, 60, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "To", NULL, NULL },
12376 { d_mr_cset_proc, 10, 70, 196, 16, 0, 0, 0, D_CSET|D_SETTABLE, 0, 0, (void *)massRecolorDest4Bit, NULL, NULL },
12377
12378 // 5
12379 { jwin_text_proc, 12, 96, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "Apply to which CSets in 8-bit tiles?", NULL, NULL },
12380 { jwin_check_proc, 12, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "0", NULL, NULL },
12381 { jwin_check_proc, 36, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "1", NULL, NULL },
12382 { jwin_check_proc, 60, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "2", NULL, NULL },
12383 { jwin_check_proc, 84, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "3", NULL, NULL },
12384 { jwin_check_proc, 108, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "4", NULL, NULL },
12385 { jwin_check_proc, 132, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "5", NULL, NULL },
12386 { jwin_check_proc, 156, 112, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "6", NULL, NULL },
12387 { jwin_check_proc, 12, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "7", NULL, NULL },
12388 { jwin_check_proc, 36, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "8", NULL, NULL },
12389 { jwin_check_proc, 60, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "9", NULL, NULL },
12390 { jwin_check_proc, 84, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "10", NULL, NULL },
12391 { jwin_check_proc, 108, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "11", NULL, NULL },
12392 { jwin_check_proc, 132, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "12", NULL, NULL },
12393 { jwin_check_proc, 156, 128, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "13", NULL, NULL },
12394
12395 // 20
12396 { jwin_check_proc, 12, 144, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "Ignore blank tiles", NULL, NULL },
12397 { jwin_func_button_proc, 14, 160, 60, 20, vc(14), vc(1), 0, 0, 0, 0, (void *) "Reset", NULL, (void*)massRecolorReset4Bit },
12398 { jwin_button_proc, 82, 160, 120, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Switch to 8-bit mode", NULL, NULL },
12399 { jwin_button_proc, 44, 188, 60, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
12400 { jwin_button_proc, 112, 188, 60, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
12401
12402 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
12403 };
12404
12405 #define MR4_SRC_COLORS 2
12406 #define MR4_DEST_COLORS 4
12407 #define MR4_8BIT_EFFECT_START 6
12408 #define MR4_IGNORE_BLANK 20
12409 #define MR4_RESET 21
12410 #define MR4_SWITCH 22
12411 #define MR4_OK 23
12412 #define MR4_CANCEL 24
12413
12414 static DIALOG recolor_8bit_dlg[] =
12415 {
12416 // (dialog proc) (x) (y) (w) (h) (fg) (bg) (key) (flags) (d1) (d2) (dp)
12417 { jwin_win_proc, 0, 0, 288, 224, 0, 0, 0, D_EXIT, 0, 0, (void *) "Recolor setup", NULL, NULL },
12418
12419 // 1
12420 { jwin_text_proc, 12, 32, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "From", NULL, NULL },
12421 { d_mr_cset_proc, 10, 42, 132, 12, 0, 0, 0, D_SETTABLE, 0, 0, (void *)massRecolorSrc8Bit, NULL, NULL },
12422 { jwin_text_proc, 12, 60, 176, 8, vc(15), vc(1), 0, 0, 0, 0, (void *) "To", NULL, NULL },
12423 { d_mr_cset_proc, 10, 70, 132, 12, 0, 0, 0, D_SETTABLE, 0, 0, (void *)massRecolorDest8Bit, NULL, NULL },
12424 { d_mr_palette_proc, 144, 32, 132, 150, vc(15), vc(1), 0, 0, 0, 0, (void *) NULL, NULL, NULL },
12425
12426 // 6
12427 { jwin_check_proc, 12, 144, 168, 8, vc(15), vc(1), 0, 0, 1, 0, (void *) "Ignore blank tiles", NULL, NULL },
12428 { jwin_func_button_proc, 50, 160, 60, 20, vc(14), vc(1), 0, 0, 0, 0, (void *) "Reset", NULL, (void*)massRecolorReset8Bit },
12429 { jwin_button_proc, 118, 160, 120, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Switch to 4-bit mode", NULL, NULL },
12430 { jwin_button_proc, 80, 188, 60, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "OK", NULL, NULL },
12431 { jwin_button_proc, 148, 188, 60, 20, vc(14), vc(1), 0, D_EXIT, 0, 0, (void *) "Cancel", NULL, NULL },
12432
12433 { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL }
12434 };
12435
12436 #define MR8_SRC_COLORS 2
12437 #define MR8_DEST_COLORS 4
12438 #define MR8_PALETTE 5
12439 #define MR8_IGNORE_BLANK 6
12440 #define MR8_RESET 7
12441 #define MR8_SWITCH 8
12442 #define MR8_OK 9
12443 #define MR8_CANCEL 10
12444
12445 static void massRecolorInit(int32_t cset)
12446 {
12447 massRecolorDraggedColor=-1;
12448 massRecolorCSet=cset;
12449
12450 recolor_4bit_dlg[0].dp2=get_zc_font(font_lfont);
12451 recolor_8bit_dlg[0].dp2=get_zc_font(font_lfont);
12452
12453 for(int32_t i=0; i<=13; i++)
12454 {
12455 if((massRecolor8BitCSets&(1<<i))!=0)
12456 recolor_4bit_dlg[MR4_8BIT_EFFECT_START+i].flags|=D_SELECTED;
12457 else
12458 recolor_4bit_dlg[MR4_8BIT_EFFECT_START+i].flags&=~D_SELECTED;
12459 }
12460
12461 if(massRecolorIgnoreBlank)
12462 {
12463 recolor_4bit_dlg[MR4_IGNORE_BLANK].flags|=D_SELECTED;
12464 recolor_8bit_dlg[MR8_IGNORE_BLANK].flags|=D_SELECTED;
12465 }
12466 else
12467 {
12468 recolor_4bit_dlg[MR4_IGNORE_BLANK].flags&=~D_SELECTED;
12469 recolor_8bit_dlg[MR8_IGNORE_BLANK].flags&=~D_SELECTED;
12470 }
12471
12472 large_dialog(recolor_4bit_dlg);
12473 large_dialog(recolor_8bit_dlg);
12474
12475 // Quick fix for large_dialog() screwing these up. It's ugly. Whatever.
12476 if((recolor_4bit_dlg[MR4_DEST_COLORS].w-4)%4!=0)
12477 {
12478 recolor_4bit_dlg[MR4_SRC_COLORS].x++;
12479 recolor_4bit_dlg[MR4_SRC_COLORS].w-=2;
12480 recolor_4bit_dlg[MR4_DEST_COLORS].x++;
12481 recolor_4bit_dlg[MR4_DEST_COLORS].w-=2;
12482
12483 recolor_8bit_dlg[MR8_SRC_COLORS].x++;
12484 recolor_8bit_dlg[MR8_SRC_COLORS].w-=2;
12485 recolor_8bit_dlg[MR8_DEST_COLORS].x++;
12486 recolor_8bit_dlg[MR8_DEST_COLORS].w-=2;
12487 recolor_8bit_dlg[MR8_PALETTE].x++;
12488 recolor_8bit_dlg[MR8_PALETTE].w-=2;
12489 recolor_8bit_dlg[MR8_PALETTE].y++;
12490 recolor_8bit_dlg[MR8_PALETTE].h-=2;
12491 }
12492 }
12493
12494 static void massRecolorApplyChanges()
12495 {
12496 massRecolor8BitCSets=0;
12497 for(int32_t i=0; i<=13; i++)
12498 {
12499 if((recolor_4bit_dlg[MR4_8BIT_EFFECT_START+i].flags&D_SELECTED)!=0)
12500 massRecolor8BitCSets|=1<<i;
12501 }
12502
12503 if(massRecolorType==MR_4BIT)
12504 massRecolorIgnoreBlank=(recolor_4bit_dlg[MR4_IGNORE_BLANK].flags&D_SELECTED)!=0;
12505 else
12506 massRecolorIgnoreBlank=(recolor_8bit_dlg[MR8_IGNORE_BLANK].flags&D_SELECTED)!=0;
12507 }
12508
12509 static bool massRecolorSetup(int32_t cset)
12510 {
12511 massRecolorInit(cset);
12512
12513 // Remember the current colors in case the user cancels.
12514 int32_t oldDest4Bit[16], oldSrc8Bit[16], oldDest8Bit[16];
12515 for(int32_t i=0; i<16; i++)
12516 {
12517 oldDest4Bit[i]=massRecolorDest4Bit[i];
12518 oldSrc8Bit[i]=massRecolorSrc8Bit[i];
12519 oldDest8Bit[i]=massRecolorDest8Bit[i];
12520 }
12521
12522 byte type=massRecolorType;
12523 int32_t ret;
12524 do
12525 {
12526 HANDLE_CLOSE_ZQDLG();
12527 if(exiting_program) break;
12528 if(type==MR_4BIT)
12529 {
12530 ret=do_zqdialog(recolor_4bit_dlg, MR4_OK);
12531 if(ret==MR4_SWITCH)
12532 type=MR_8BIT;
12533 }
12534 else
12535 {
12536 ret=do_zqdialog(recolor_8bit_dlg, MR8_OK);
12537 if(ret==MR8_SWITCH)
12538 type=MR_4BIT;
12539 }
12540 } while(ret==MR4_SWITCH || ret==MR8_SWITCH);
12541
12542 if(ret!=MR4_OK && ret!=MR8_OK) // Canceled
12543 {
12544 for(int32_t i=0; i<16; i++)
12545 {
12546 massRecolorDest4Bit[i]=oldDest4Bit[i];
12547 massRecolorSrc8Bit[i]=oldSrc8Bit[i];
12548 massRecolorDest8Bit[i]=oldDest8Bit[i];
12549 }
12550 return false;
12551 }
12552
12553 // OK
12554 massRecolorType=type;
12555 massRecolorApplyChanges();
12556 return true;
12557 }
12558
12559 static void massRecolorApply4Bit(int32_t tile)
12560 {
12561 byte buf[256];
12562 unpack_tile(newtilebuf, tile, 0, true);
12563
12564 if(newtilebuf[tile].format==tf4Bit)
12565 {
12566 for(int32_t i=0; i<256; i++)
12567 buf[i]=massRecolorDest4Bit[unpackbuf[i]];
12568 }
12569 else // 8-bit
12570 {
12571 for(int32_t i=0; i<256; i++)
12572 {
12573 word cset=unpackbuf[i]>>4;
12574 if((massRecolor8BitCSets&(1<<cset))!=0) // Recolor this CSet?
12575 {
12576 word color=unpackbuf[i]&15;
12577 buf[i]=(cset<<4)|massRecolorDest4Bit[color];
12578 }
12579 else
12580 buf[i]=unpackbuf[i];
12581 }
12582 }
12583
12584 pack_tile(newtilebuf, buf, tile);
12585 }
12586
12587 static void massRecolorApply8Bit(int32_t tile)
12588 {
12589 byte buf[256];
12590 unpack_tile(newtilebuf, tile, 0, true);
12591
12592 for(int32_t i=0; i<256; i++)
12593 {
12594 byte color=unpackbuf[i];
12595 for(int32_t j=0; j<16; j++)
12596 {
12597 if(massRecolorSrc8Bit[j]==color)
12598 {
12599 color=massRecolorDest8Bit[j];
12600 break;
12601 }
12602 }
12603 buf[i]=color;
12604 }
12605
12606 pack_tile(newtilebuf, buf, tile);
12607 }
12608
12609 static void massRecolorApply(int32_t tile)
12610 {
12611 if(massRecolorIgnoreBlank && blank_tile_table[tile])
12612 return;
12613
12614 if(massRecolorType==MR_4BIT)
12615 massRecolorApply4Bit(tile);
12616 else // 8-bit
12617 {
12618 if(newtilebuf[tile].format==tf4Bit)
12619 return;
12620 massRecolorApply8Bit(tile);
12621 }
12622 }
12623
12624 static void massRecolorReset4Bit()
12625 {
12626 for(int32_t i=0; i<16; i++)
12627 massRecolorDest4Bit[i]=i;
12628 recolor_4bit_dlg[MR4_DEST_COLORS].flags|=D_DIRTY;
12629 }
12630
12631 static void massRecolorReset8Bit()
12632 {
12633 for(int32_t i=0; i<16; i++)
12634 {
12635 massRecolorSrc8Bit[i]=0;
12636 massRecolorDest8Bit[i]=0;
12637 }
12638
12639 recolor_8bit_dlg[MR8_SRC_COLORS].flags|=D_DIRTY;
12640 recolor_8bit_dlg[MR8_DEST_COLORS].flags|=D_DIRTY;
12641 }
12642
12643 6 void center_zq_tiles_dialogs()
12644 {
12645 6 jwin_center_dialog(create_relational_tiles_dlg);
12646 6 jwin_center_dialog(icon_dlg);
12647 6 jwin_center_dialog(leech_dlg);
12648 6 jwin_center_dialog(move_textbox_list_dlg);
12649 6 jwin_center_dialog(recolor_4bit_dlg);
12650 6 jwin_center_dialog(recolor_8bit_dlg);
12651 6 }
12652
12653 //.ZCOMBO
12654
12655 int32_t readcombo_loop(PACKFILE* f, word section_version, newcombo& temp_combo);
12656 int32_t writecombo_loop(PACKFILE *f, word section_version, newcombo const& tmp_cmb);
12657
12658 int32_t readcombofile_old(PACKFILE *f, int32_t skip, byte nooverwrite, int32_t zversion,
12659 dword section_version, dword section_cversion, int32_t index, int32_t count)
12660 {
12661 newcombo temp_combo;
12662 for ( int32_t tilect = 0; tilect < count; tilect++ )
12663 {
12664 temp_combo.clear();
12665 if(!p_igetw(&temp_combo.tile,f))
12666 {
12667 return 0;
12668 }
12669 temp_combo.o_tile = temp_combo.tile;
12670
12671 if(!p_getc(&temp_combo.flip,f))
12672 {
12673 return 0;
12674 }
12675
12676 if(!p_getc(&temp_combo.walk,f))
12677 {
12678 return 0;
12679 }
12680
12681 if(!p_getc(&temp_combo.type,f))
12682 {
12683 return 0;
12684 }
12685
12686 if(!p_getc(&temp_combo.csets,f))
12687 {
12688 return 0;
12689 }
12690
12691 if(!p_getc(&temp_combo.frames,f))
12692 {
12693 return 0;
12694 }
12695
12696 if(!p_getc(&temp_combo.speed,f))
12697 {
12698 return 0;
12699 }
12700
12701 if(!p_igetw(&temp_combo.nextcombo,f))
12702 {
12703 return 0;
12704 }
12705
12706 if(!p_getc(&temp_combo.nextcset,f))
12707 {
12708 return 0;
12709 }
12710
12711 if(!p_getc(&temp_combo.flag,f))
12712 {
12713 return 0;
12714 }
12715
12716 if(!p_getc(&temp_combo.skipanim,f))
12717 {
12718 return 0;
12719 }
12720
12721 if(!p_igetw(&temp_combo.nexttimer,f))
12722 {
12723 return 0;
12724 }
12725
12726 if(!p_getc(&temp_combo.skipanimy,f))
12727 {
12728 return 0;
12729 }
12730
12731 if(!p_getc(&temp_combo.animflags,f))
12732 {
12733 return 0;
12734 }
12735
12736 //2.55 starts here
12737 if ( zversion >= 0x255 )
12738 {
12739 if ( section_version >= 12 )
12740 {
12741 for ( int32_t q = 0; q < NUM_COMBO_ATTRIBUTES; q++ )
12742 {
12743 if(!p_igetl(&temp_combo.attributes[q],f))
12744 {
12745 return 0;
12746 }
12747 }
12748 if(!p_igetl(&temp_combo.usrflags,f))
12749 {
12750 return 0;
12751 }
12752 for ( int32_t q = 0; q < 3; q++ )
12753 {
12754 if(!p_igetl(&temp_combo.triggerflags[q],f))
12755 {
12756 return 0;
12757 }
12758 }
12759
12760 if(!p_igetl(&temp_combo.triggerlevel,f))
12761 {
12762 return 0;
12763 }
12764 if(section_version >= 22)
12765 {
12766 if(!p_getc(&temp_combo.triggerbtn,f))
12767 {
12768 return 0;
12769 }
12770 }
12771 if(section_version < 23)
12772 {
12773 switch(temp_combo.type) //combotriggerCMBTYPEFX now required for combotype-specific effects
12774 {
12775 case cSCRIPT1: case cSCRIPT2: case cSCRIPT3: case cSCRIPT4: case cSCRIPT5:
12776 case cSCRIPT6: case cSCRIPT7: case cSCRIPT8: case cSCRIPT9: case cSCRIPT10:
12777 case cTRIGGERGENERIC: case cCSWITCH:
12778 temp_combo.triggerflags[0] |= combotriggerCMBTYPEFX;
12779 }
12780 }
12781 if(section_version >= 24)
12782 {
12783 if(!p_getc(&temp_combo.triggeritem,f))
12784 {
12785 return 0;
12786 }
12787 if(!p_getc(&temp_combo.trigtimer,f))
12788 {
12789 return 0;
12790 }
12791 }
12792 if(section_version >= 25)
12793 {
12794 if(!p_getc(&temp_combo.trigsfx,f))
12795 {
12796 return 0;
12797 }
12798 }
12799 else
12800 {
12801 switch(temp_combo.type)
12802 {
12803 case cLOCKBLOCK: case cBOSSLOCKBLOCK:
12804 if(!(temp_combo.usrflags & cflag3))
12805 temp_combo.attribytes[3] = WAV_DOOR;
12806 temp_combo.usrflags &= ~cflag3;
12807 break;
12808 }
12809 }
12810 if(section_version < 26)
12811 {
12812 if(temp_combo.type == cARMOS)
12813 {
12814 if(temp_combo.usrflags & cflag1)
12815 temp_combo.usrflags |= cflag3;
12816 }
12817 }
12818 if(section_version >= 27)
12819 {
12820 if(!p_igetl(&temp_combo.trigchange,f))
12821 {
12822 return qe_invalid;
12823 }
12824 }
12825 else
12826 {
12827 if(temp_combo.triggerflags[0] & 0x00040000) //'next'
12828 temp_combo.trigchange = 1;
12829 else if(temp_combo.triggerflags[0] & 0x00080000) //'prev'
12830 temp_combo.trigchange = -1;
12831 else temp_combo.trigchange = 0;
12832 temp_combo.triggerflags[0] &= ~(0x00040000|0x00080000);
12833 }
12834 if(section_version >= 29)
12835 {
12836 if(!p_igetw(&temp_combo.trigprox,f))
12837 {
12838 return qe_invalid;
12839 }
12840 if(!p_getc(&temp_combo.trigctr,f))
12841 {
12842 return qe_invalid;
12843 }
12844 if(!p_igetl(&temp_combo.trigctramnt,f))
12845 {
12846 return qe_invalid;
12847 }
12848 }
12849 else
12850 {
12851 temp_combo.trigprox = 0;
12852 temp_combo.trigctr = 0;
12853 temp_combo.trigctramnt = 0;
12854 }
12855 if(section_version >= 30)
12856 {
12857 if(!p_getc(&temp_combo.triglbeam,f))
12858 {
12859 return qe_invalid;
12860 }
12861 }
12862 else temp_combo.triglbeam = 0;
12863 if(section_version >= 31)
12864 {
12865 if(!p_getc(&temp_combo.trigcschange,f))
12866 {
12867 return qe_invalid;
12868 }
12869 if(!p_igetw(&temp_combo.spawnitem,f))
12870 {
12871 return qe_invalid;
12872 }
12873 if(!p_igetw(&temp_combo.spawnenemy,f))
12874 {
12875 return qe_invalid;
12876 }
12877 if(!p_getc(&temp_combo.exstate,f))
12878 {
12879 return qe_invalid;
12880 }
12881 if(!p_igetl(&temp_combo.spawnip,f))
12882 {
12883 return qe_invalid;
12884 }
12885 if(!p_getc(&temp_combo.trigcopycat,f))
12886 {
12887 return qe_invalid;
12888 }
12889 }
12890 else
12891 {
12892 temp_combo.trigcschange = 0;
12893 temp_combo.spawnitem = 0;
12894 temp_combo.spawnenemy = 0;
12895 temp_combo.exstate = -1;
12896 temp_combo.spawnip = 0;
12897 temp_combo.trigcopycat = 0;
12898 }
12899 if(section_version >= 32)
12900 {
12901 if(!p_getc(&temp_combo.trigcooldown,f))
12902 {
12903 return qe_invalid;
12904 }
12905 }
12906 else
12907 {
12908 temp_combo.trigcooldown = 0;
12909 }
12910 char label[12];
12911 label[11] = '\0';
12912 for ( int32_t q = 0; q < 11; q++ )
12913 {
12914 if(!p_getc(&label[q],f))
12915 {
12916 return 0;
12917 }
12918 }
12919 temp_combo.label = label;
12920 }
12921 if ( section_version >= 13 )
12922 {
12923 for ( int32_t q = 0; q < NUM_COMBO_ATTRIBUTES; q++ )
12924 {
12925 if(!p_getc(&temp_combo.attribytes[q],f))
12926 {
12927 return 0;
12928 }
12929 }
12930
12931 }
12932 }
12933
12934 if ( !(skip && (index+(tilect-1)) < skip) ) //is -1 still needed here?
12935 {
12936 if ( !nooverwrite || combobuf[index+tilect].is_blank() )
12937 {
12938 combobuf[index+(tilect)] = temp_combo;
12939 }
12940 }
12941 }
12942
12943 return 1;
12944 }
12945
12946 int32_t readcombofile(PACKFILE *f, int32_t skip, byte nooverwrite, int32_t start)
12947 {
12948 dword section_version=0;
12949 dword section_cversion=0;
12950 int32_t zversion = 0;
12951 int32_t zbuild = 0;
12952
12953 if(!p_igetl(&zversion,f))
12954 {
12955 return 0;
12956 }
12957 if(!p_igetl(&zbuild,f))
12958 {
12959 return 0;
12960 }
12961 if(!p_igetw(&section_version,f))
12962 {
12963 return 0;
12964 }
12965 if(!p_igetw(&section_cversion,f))
12966 {
12967 return 0;
12968 }
12969
12970 if ( zversion > ZELDA_VERSION )
12971 {
12972 al_trace("Cannot read .zcombo packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
12973 return 0;
12974 }
12975
12976 else if ( ( section_version > V_COMBOS ) || ( section_version == V_COMBOS && section_cversion > CV_COMBOS ) )
12977 {
12978 al_trace("Cannot read .zcombo packfile made using V_COMBOS (%d) subversion (%d)\n", section_version, section_cversion);
12979 return 0;
12980
12981 }
12982 else
12983 {
12984 al_trace("Reading a .zcombo packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
12985 }
12986
12987 int32_t index = 0;
12988 int32_t count = 0;
12989
12990 //tile id
12991 if(!p_igetl(&index,f))
12992 {
12993 return 0;
12994 }
12995 if(start > -1) index = start;
12996 // al_trace("Reading combo: index(%d)\n", index);
12997
12998 //tile count
12999 if(!p_igetl(&count,f))
13000 {
13001 return 0;
13002 }
13003 // al_trace("Reading combo: count(%d)\n", count);
13004 reset_combo_animations();
13005 reset_combo_animations2();
13006
13007 if(section_version < 33)
13008 return readcombofile_old(f,skip,nooverwrite,zversion,section_version,section_cversion,index,count);
13009
13010 newcombo temp_combo;
13011 size_t end = index+count;
13012 for ( size_t q = index; q < end; q++ )
13013 {
13014 auto ret = readcombo_loop(f,section_version,temp_combo);
13015 if(ret) return 0;
13016
13017 if ( !(skip && q-1 < skip) )
13018 {
13019 if ( !nooverwrite || combobuf[q].is_blank() )
13020 {
13021 combobuf[q] = temp_combo;
13022 }
13023 }
13024 }
13025
13026 return 1;
13027 }
13028 int32_t readcombofile_to_location(PACKFILE *f, int32_t start, byte nooverwrite, int32_t skip)
13029 {
13030 return readcombofile(f,skip,nooverwrite,start);
13031 }
13032 int32_t writecombofile(PACKFILE *f, int32_t index, int32_t count)
13033 {
13034 dword section_version=V_COMBOS;
13035 dword section_cversion=CV_COMBOS;
13036 int32_t zversion = ZELDA_VERSION;
13037 int32_t zbuild = VERSION_BUILD;
13038
13039 if(!p_iputl(zversion,f))
13040 {
13041 return 0;
13042 }
13043 if(!p_iputl(zbuild,f))
13044 {
13045 return 0;
13046 }
13047 if(!p_iputw(section_version,f))
13048 {
13049 return 0;
13050 }
13051
13052 if(!p_iputw(section_cversion,f))
13053 {
13054 return 0;
13055 }
13056
13057 //start tile id
13058 if(!p_iputl(index,f))
13059 {
13060 return 0;
13061 }
13062
13063 //count
13064 if(!p_iputl(count,f))
13065 {
13066 return 0;
13067 }
13068 reset_combo_animations();
13069 reset_combo_animations2();
13070 size_t end = index+count;
13071 for(size_t q = index; q < end; ++q)
13072 {
13073 if(writecombo_loop(f, section_version, combobuf[q]))
13074 return 0;
13075 }
13076
13077 return 1;
13078
13079 }
13080
13081 //.ZALIAS
13082
13083
13084 //.ZALIAS
13085
13086 int32_t readcomboaliasfile(PACKFILE *f)
13087 {
13088 dword section_version=0;
13089 dword section_cversion=0;
13090 int32_t zversion = 0;
13091 int32_t zbuild = 0;
13092 word tempword = 0;
13093
13094 if(!p_igetl(&zversion,f))
13095 {
13096 return 0;
13097 }
13098 if(!p_igetl(&zbuild,f))
13099 {
13100 return 0;
13101 }
13102 if(!p_igetw(&section_version,f))
13103 {
13104 return 0;
13105 }
13106 if(!p_igetw(&section_cversion,f))
13107 {
13108 return 0;
13109 }
13110 al_trace("readoneweapon section_version: %d\n", section_version);
13111 al_trace("readoneweapon section_cversion: %d\n", section_cversion);
13112
13113 if ( zversion > ZELDA_VERSION )
13114 {
13115 al_trace("Cannot read .zalias packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
13116 return 0;
13117 }
13118
13119 else if ( ( section_version > V_COMBOALIASES ) || ( section_version == V_COMBOALIASES && section_cversion > CV_COMBOALIASES ) )
13120 {
13121 al_trace("Cannot read .zalias packfile made using V_COMBOALIASES (%d) subversion (%d)\n", section_version, section_cversion);
13122 return 0;
13123
13124 }
13125 else
13126 {
13127 al_trace("Reading a .zalias packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
13128 }
13129
13130 int32_t index = 0;
13131 int32_t count = 0;
13132 int32_t count2 = 0;
13133 byte tempcset = 0;
13134
13135 //tile id
13136 if(!p_igetl(&index,f))
13137 {
13138 return 0;
13139 }
13140 al_trace("Reading combo: index(%d)\n", index);
13141
13142 //tile count
13143 if(!p_igetl(&count,f))
13144 {
13145 return 0;
13146 }
13147 al_trace("Reading combo: count(%d)\n", count);
13148
13149 combo_alias temp_alias;
13150
13151 for ( int32_t tilect = 0; tilect < count; tilect++ )
13152 {
13153 temp_alias.clear();
13154 if(!p_igetw(&temp_alias.combo,f))
13155 {
13156 return 0;
13157 }
13158
13159 if(!p_getc(&temp_alias.cset,f))
13160 {
13161 return 0;
13162 }
13163
13164
13165
13166 if(!p_igetl(&count2,f))
13167 {
13168 return 0;
13169 }
13170 al_trace("Read, Combo alias count is: %d\n", count2);
13171 if(!p_getc(&temp_alias.width,f))
13172 {
13173 return 0;
13174 }
13175
13176 if(!p_getc(&temp_alias.height,f))
13177 {
13178 return 0;
13179 }
13180
13181 if(!p_getc(&temp_alias.layermask,f))
13182 {
13183 return 0;
13184 }
13185 //These values are flexible, and may differ in size, so we delete them
13186 //and recreate them at the correct size on the pointer.
13187 temp_alias.combos.clear();
13188 temp_alias.csets.clear();
13189 for(int32_t k=0; k<count2; k++)
13190 {
13191 if(!p_igetw(&tempword,f))
13192 {
13193 return 0;
13194 }
13195 else
13196 {
13197
13198
13199 temp_alias.combos[k] = tempword;
13200 }
13201 }
13202
13203 for(int32_t k=0; k<count2; k++)
13204 {
13205 if(!p_getc(&tempcset,f))
13206 //if(!p_getc(&temp_alias.csets[k],f))
13207 {
13208 return 0;
13209 }
13210 else
13211 {
13212
13213 temp_alias.csets[k] = tempcset;
13214 }
13215 }
13216 combo_aliases[index+(tilect)] = temp_alias;
13217 }
13218
13219 //::memcpy(&(newtilebuf[tile_index]),&temptile,sizeof(tiledata));
13220
13221
13222 return 1;
13223
13224 }
13225
13226 int32_t readcomboaliasfile_to_location(PACKFILE *f, int32_t start)
13227 {
13228 dword section_version=0;
13229 dword section_cversion=0;
13230 int32_t zversion = 0;
13231 int32_t zbuild = 0;
13232
13233 if(!p_igetl(&zversion,f))
13234 {
13235 return 0;
13236 }
13237 if(!p_igetl(&zbuild,f))
13238 {
13239 return 0;
13240 }
13241 if(!p_igetw(&section_version,f))
13242 {
13243 return 0;
13244 }
13245 if(!p_igetw(&section_cversion,f))
13246 {
13247 return 0;
13248 }
13249 al_trace("readcomboaliasfile_to_location section_version: %d\n", section_version);
13250 al_trace("readcomboaliasfile_to_location section_cversion: %d\n", section_cversion);
13251
13252 if ( zversion > ZELDA_VERSION )
13253 {
13254 al_trace("Cannot read .zalias packfile made in ZC version (%x) in this version of ZC (%x)\n", zversion, ZELDA_VERSION);
13255 return 0;
13256 }
13257 else if ( ( section_version > V_COMBOALIASES ) || ( section_version == V_COMBOALIASES && section_cversion > CV_COMBOALIASES ) )
13258 {
13259 al_trace("Cannot read .zalias packfile made using V_COMBOALIASES (%d) subversion (%d)\n", section_version, section_cversion);
13260 return 0;
13261
13262 }
13263 else
13264 {
13265 al_trace("Reading a .zalias packfile made in ZC Version: %x, Build: %d\n", zversion, zbuild);
13266 }
13267
13268 int32_t index = 0;
13269 int32_t count = 0;
13270 int32_t count2 = 0;
13271 byte tempcset = 0;
13272 word tempword = 0;
13273
13274
13275 //tile id
13276 if(!p_igetl(&index,f))
13277 {
13278 return 0;
13279 }
13280 al_trace("Reading tile: index(%d)\n", index);
13281
13282 //tile count
13283 if(!p_igetl(&count,f))
13284 {
13285 return 0;
13286 }
13287 al_trace("Reading tile: count(%d)\n", count);
13288
13289
13290 combo_alias temp_alias;
13291
13292 for ( int32_t tilect = 0; tilect < count; tilect++ )
13293 {
13294 temp_alias.clear();
13295 if(!p_igetw(&temp_alias.combo,f))
13296 {
13297 return 0;
13298 }
13299
13300 if(!p_getc(&temp_alias.cset,f))
13301 {
13302 return 0;
13303 }
13304
13305 int32_t count2 = 0;
13306
13307 if(!p_igetl(&count2,f))
13308 {
13309 return 0;
13310 }
13311
13312 if(!p_getc(&temp_alias.width,f))
13313 {
13314 return 0;
13315 }
13316
13317 if(!p_getc(&temp_alias.height,f))
13318 {
13319 return 0;
13320 }
13321
13322 if(!p_getc(&temp_alias.layermask,f))
13323 {
13324 return 0;
13325 }
13326 //These values are flexible, and may differ in size, so we delete them
13327 //and recreate them at the correct size on the pointer.
13328 temp_alias.combos.clear();
13329 temp_alias.csets.clear();
13330
13331 for(int32_t k=0; k<count2; k++)
13332 {
13333 if(!p_igetw(&tempword,f))
13334 {
13335 return 0;
13336 }
13337 else
13338 {
13339 temp_alias.combos[k] = tempword;
13340 }
13341 }
13342
13343 for(int32_t k=0; k<count2; k++)
13344 {
13345 if(!p_getc(&tempcset,f))
13346 {
13347 return 0;
13348 }
13349 else
13350 {
13351 temp_alias.csets[k] = tempcset;
13352 }
13353 }
13354
13355 if ( start+(tilect) < MAXCOMBOALIASES )
13356 {
13357 combo_aliases[start + (tilect)] = temp_alias;
13358 }
13359 }
13360 return 1;
13361 }
13362 int32_t writecomboaliasfile(PACKFILE *f, int32_t index, int32_t count)
13363 {
13364 al_trace("Running writecomboaliasfile\n");
13365 dword section_version=V_COMBOALIASES;
13366 dword section_cversion=CV_COMBOALIASES;
13367 int32_t zversion = ZELDA_VERSION;
13368 int32_t zbuild = VERSION_BUILD;
13369
13370 if(!p_iputl(zversion,f))
13371 {
13372 return 0;
13373 }
13374 if(!p_iputl(zbuild,f))
13375 {
13376 return 0;
13377 }
13378 if(!p_iputw(section_version,f))
13379 {
13380 return 0;
13381 }
13382
13383 if(!p_iputw(section_cversion,f))
13384 {
13385 return 0;
13386 }
13387
13388 //start tile id
13389 if(!p_iputl(index,f))
13390 {
13391 return 0;
13392 }
13393
13394 //count
13395 if(!p_iputl(count,f))
13396 {
13397 return 0;
13398 }
13399
13400 for ( int32_t tilect = 0; tilect < count; tilect++ )
13401 {
13402
13403 if(!p_iputw(combo_aliases[index+(tilect)].combo,f))
13404 {
13405 return 0;
13406 }
13407
13408 if(!p_putc(combo_aliases[index+(tilect)].cset,f))
13409 {
13410 return 0;
13411 }
13412
13413 int32_t count2 = ((combo_aliases[index+(tilect)].width+1)*(combo_aliases[index+(tilect)].height+1))*(comboa_lmasktotal(combo_aliases[index+(tilect)].layermask)+1);
13414
13415 if(!p_iputl(count2,f))
13416 {
13417 return 0;
13418 }
13419 al_trace("Write`, Combo alias count is: %d\n", count2);
13420
13421 if(!p_putc(combo_aliases[index+(tilect)].width,f))
13422 {
13423 return 0;
13424 }
13425
13426 if(!p_putc(combo_aliases[index+(tilect)].height,f))
13427 {
13428 return 0;
13429 }
13430
13431 if(!p_putc(combo_aliases[index+(tilect)].layermask,f))
13432 {
13433 return 0;
13434 }
13435
13436 for(int32_t k=0; k<count2; k++)
13437 {
13438 if(!p_iputw(combo_aliases[index+(tilect)].combos[k],f))
13439 {
13440 return 0;
13441 }
13442 }
13443
13444 for(int32_t k=0; k<count2; k++)
13445 {
13446 if(!p_putc(combo_aliases[index+(tilect)].csets[k],f))
13447 {
13448 return 0;
13449 }
13450 }
13451 }
13452
13453 return 1;
13454
13455 }
13456